• 真值:就是带有正负号的实际十进制数,比如上面例子中,+108D就是真值
  • 机器数:机器数就是一个数在计算机中的二进制表示形式,注意机器数是由符号位和数值位构成的,比如上面例子中,01101100 就是机器数。

-156D(真值)= 110011100B(机器数)

1. 原码

十进制 原码
2 0000 0010
-2 1000 0010

原码 补码 反码 移码 - 图1
简单点理解,原码就是符号位加上真值(二进制)的绝对值,同时用逗号将符号位和数值位隔开。比如,+1 就是 0,0000001,-1 就是 1,0000001

2. 反码

十进制 原码 反码
2 0000 0010 0000 0010
-2 1000 0010 1111 1101

原码 补码 反码 移码 - 图2
反码很好理解:

  • 正数:反码等于原码等于补码;
  • 负数:反码等于原码保持符号位不变的情况下其余各位取反。也就是说,补码=反码+1
  • 反码的反码等于原码,这可以用来根据反码求原码。

我们来看一个特殊的运算:

  1. 1-1
  2. = 1+(-1)
  3. = 0000 0001(反码) + 1111 1110(反码)
  4. = 1111 1111(反码)
  5. = 1000 0000(原码)
  6. = -0
  7. 复制代码

我们来看一个特殊的运算:

  1. 0+0
  2. = 0000 0000(反码) + 0000 0000(反码)
  3. = 0000 0000(反码)
  4. = 0000 0000(原码)
  5. = 0
  6. 复制代码

我们可以看到1000 0000表示-0,0000 0000表示0,虽然-0和0是一样的,但是在用原码和反码表示时是不同的,我们可以理解为在用一个字节表示数字取值范围时,这些数字中多了一个-0,所以导致我们在用反码直接运算时符号位可以直接参加运算,但是结果会不对。

3. 补码

十进制 原码 反码 补码
2 0000 0010 0000 0010 0000 0010
-2 1000 0010 1111 1101 1111 1110

原码 补码 反码 移码 - 图3

  • 对于正数:正数的补码和原码相同;
  • 对于负数:负数的补码等于其原码在保持符号位不变的情况下,其余各位取反,末位加一(取反加一)注意,补码的补码等于原码,这可以用来根据补码求原码。

    4. 移码

    补码存在的问题是,仅从补码本身来看,很难比较两个数的大小,为此引入了移码的概念。移码指的是在真值(二进制)的基础上加上一个偏移量,通常这个偏移量是2^n。其中,n是数值位的位数。例如,对于-10101,其移码是2^7+(-10101)=10000000+(010101)=0,1101011。 当然,我们有简单的方法可以计算一个数的移码:不管正数还是负数,其移码都等于补码的符号位取反
    原码 补码 反码 移码 - 图4

5. 定点数的加减运算

5.1 补码的加减运算

定点数的加减运算实际上就是补码的加减运算。我们来看一个例子:

假设机器字长为 8 位(含1位符号位),A=15,B=-24,现在求 A+B 和 A-B。

A 的补码是 0,0001111,B 的补码是 1,1101000,那么 0,0001111+1,1101000=1,1110111,转化为原码,再转化为真值,得到 -9,这是正确的。同理,A-B 就是 A+(-B),-B 的补码是 0,0011000,那么 0,0001111+0,0011000=0,0100111,最后转化为真值,得到 +39,这也是正确的。 我们再来看另一个例子:

假设机器字长为 8 位(含1位符号位),A=15,B=-24,C=124,现在求 A+C 和 B-C。

我们同样按照上面的流程来进行计算,最后得出:A+C 结果是 -117,B-C 结果是 +108,这两个都是错误的。为什么会出现这样的情况呢?

5.2 溢出

运算结果太小或者太大
原码 补码 反码 移码 - 图5
原码 补码 反码 移码 - 图6
三位二进制数可以表示的范围
现在我们进行 2+2 操作,那么就是 010+010,结果就是 100,这已经超出了正数可以表示的最大范围,也就是发生了上溢。所以此时得到的是 -4,这是一个错误的结果。

5.3 溢出的判断

正数和负数相加是不会发生溢出的,因为其结果必然在可以表示的范围内,唯一可能会发生溢出的情况,要么是正数加正数,要么是负数加负数

(1)一位符号位变化:比较操作数符号位与结果数符号位

原码 补码 反码 移码 - 图7

(2)二位符号位变化:比较符号位和最高数值位的进位情况

image.png

(3)两位符号位变化:

正数符号为 00,负数符号为 11。计算机只需要看结果数就能知道是否发生溢出 —— 只要结果数的两位符号位相异,那么就一定是发生了溢出。
原码 补码 反码 移码 - 图9


深入理解计算机系统:定点数的表示和运算 一文搞明白位运算、补码、反码、原码