源码-反码-补码
文章目录
概念
机器数
真值
- 真值符号部分
- 真值部分
举例:
-1的真值是:1000 0001
, 其中真值符号区域为最高位的1
,他的真值区域为000 0001
。
- 原码
|
|
- 反码:
- 正数的反码是其本身
- 负数的反码是在其原码的基础上, 符号位不变,其余各个位取反.
十进制数 | 带符号位二进制原码 | 带符号位二进制补码 |
---|---|---|
-8 | N | 1000 |
-7 | 1111 | 1001 |
-6 | 1110 | 1010 |
-5 | 1101 | 1011 |
-4 | 1100 | 1100 |
-3 | 1011 | 1101 |
-2 | 1010 | 1110 |
-1 | 1001 | 1111 |
-0 | 1000 | 0000 |
+0 | 0000 | 0000 |
1 | 0001 | 0001 |
2 | 0010 | 0010 |
3 | 0011 | 0011 |
4 | 0100 | 0100 |
5 | 0101 | 0101 |
6 | 0110 | 0110 |
7 | 0111 | 0111 |
- 补码:
- 正数的补码就是其本身
- 负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码基础上+1)
计算机要使用一定的编码方式进行存储. 原码, 反码, 补码是机器存储一个具体数字的编码方式. 但为什么需要三种不同的编码方式呢?
使用原码,反码和补码的原因
人脑与机器计算的差异
人脑可以知道第一位是符号位, 在计算的时候我们会根据符号位, 选择对真值区域的加减。但是对于计算机, 加减乘数已经是最基础的运算, 要设计的尽量简单. 计算机辨别"符号位"显然会让计算机的基础电路设计变得十分复杂! 于是人们转而设计出将符号位也参与运算的方法。
反码诞生原因
如果只使用原码,当我们计算1-1=0
=> 1 - 1 = 1 + (-1) = [00000001]原 + [10000001]原 = [10000010]原 = -2
,这显然不符合我们的预期。
为了解决原码符号位也参与运算做减法的问题, 出现了反码,会到前面的例子,用反码来表示一下:1 - 1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原= [0000 0001]反 + [1111 1110]反 = [1111 1111]反 = [1000 0000]原 = -0
用反码计算减法, 结果真值区域是正确的
再看一个1-2
=>[0000 0001]原 + [1000 0010]原= [0000 0001]反 + [1111 1101]反 = [1111 1110]反 = [1000 0001]原
,就为-1
但对于0这个特殊的数值. 虽然人们理解上+0和-0是一样的, 但是0带符号是没有任何意义的. 且会用[0000 0000]原和[1000 0000]原两个编码表示0,导致浪费。
补码的诞生
于是补码的出现, 解决了0的符号以及两个编码的问题: 1-1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原 = [0000 0001]补 + [1111 1111]补 = [0000 0000]补=[0000 0000]原
这样0用[0000 0000]表示, 而以前出现问题的-0则不存在了.而且可以用[1000 0000]表示-128:
重探反码
计算机巧妙地把符号位参与运算, 并且将减法变成了加法, 背后蕴含了怎样的数学原理呢?
将钟表想象成是一个1位的12进制数. 如果当前时间是6点, 我希望将时间设置成4点, 需要怎么做呢?我们可以:
|
|
2,3方法中的mod是指取模操作, 16 mod 12 =4 即用16除以12后的余数是4.
所以钟表往回拨(减法)的结果可以用往前拨(加法)替代!
现在的焦点就落在了如何用一个正数, 来替代一个负数. 上面的例子我们能感觉出来一些端倪, 发现一些规律. 但是数学是严谨的. 不能靠感觉.
模运算的定义
定义:对于任意实数x,y,可以有 $$ x \bmod y=x-y\left[\frac{x}{y}\right], \quad y \neq 0 $$ 取下界
-3 mod 2:
|
|
同余
|
|
同余定理的反身性
|
|
同余的线性运算
- 同余式相加:若 $$ a \equiv b(\bmod m) , c \equiv d(\bmod m) ,则 a \pm c \equiv b d \mathrm{m} (mod m) $$
- 同余式相乘:若 $$ a \equiv b(\bmod m) , c \equiv d(\bmod m) ,则 a c \equiv b d(\bmod m) $$
一个数的反码, 实际上是这个数对于一个膜的同余数. 而这个膜并不是我们的二进制, 而是所能表示的最大值
2-1=2+(-1) = [0000 0010]原 + [1000 0001]原= [0000 0010]反 + [1111 1110]反 = [0000 0010]补 + [1111 1111]补
-1的反码表示是1111 1110. 如果这里将[1111 1110]认为是原码, 则[1111 1110]原 = -126, 这里将符号位除去(符号位是参与计算的, 正好和溢出的最高位形成正确的运算结果), 即认为是126
|
|
|
|
文章作者 zput
上次更新 2023-01-10