机器数有三种不同的形式——原码,反码和补码
正数的原码,反码,补码都相同,也就是说,只有负数的表示中才有原码,反码,补码的区分
原码 | 使用最高位作为符号位,剩下的7位表示数字的表示方法(-127~+127) |
反码 | 符号位不变,其余位按位取反(-127~+127) |
补码 | 符号位不变,其余位按位取反后加1(-128~+127) |
通常,计算机中的数用补码表示,这种表示方法的优势在于——减法可以用补码的加法来计算
溢出——有符号数的运算结果超出了-128~+127的表示范围,破坏了符号位
补码的加减法运算
微机中,凡是带符号的数,一律用补码表示,运算结果自然也是补码,其特点是——符号位和数值位一起参与运算,并自动获得结果(包含符号位和数值位)
补码的加法
进行补码的加法运算的时候,无论两个数是正数还是负数——补码的和等于和的补码,补码的差等于差的补码(其中减法运算,求[-Y]的补码时,可以对[Y]的补码连同符号一起“取反加1”)
运算过程中,只要结果不超过8位补码表示的范围,其结果总是正确的,微机中,专门设计了一个溢出标志位,如果运算过程发生溢出,溢出标志位就会置1,此时的结果就是错的
在单片机上,溢出标志位为程序状态寄存器上的PSW.2位的OV,执行算术运算的时候,由硬件清0或置1,以指示运算结果的溢出与否
该博客举例说明了补码加减法的计算过程,以及补码对硬件进行简化的原理
- 使用原码计算时,会忽略符号位,直接计算,其值是符号位+计算值,只要参与运算的值有负的,结果就是两个数的和的负数
- 使用反码进行计算时,由于反码计算十进制的表达式:1 - 1 = 0,出现了-0,这样就和正经的0重复了
1 - 1 = 1 + (-1) = [0000 0001]原+ [1000 0001]原= [0000 0001]反+ [1111 1110]反= [1111 1111]反= [1000 0000]原= -0
-
使用补码计算的话,完美解决了两个0的问题,同时还为其表示范围又增加了一位-128:
(-1) + (-127) = [1000 0001]原+ [1111 1111]原= [1111 1111]补+ [1000 0001]补= [1000 0000]补
由于-128是在补码表示中,多的一位(-0)表示,所以-128不存在原码和反码的表示形式,由补码算出来的 [0000 0000]原 是不正确的
反码计算合理性——对模同余
x和y对于模m同余:x mod y = x - y L x / y J
上面公式的意思是——x mod y等于 x 减去 y 乘上 x与y的商的下界,如:
(-2) mod 12 = 12-2=10 (-2) mod 12 = -2 - 12*[-2/12] = -2 -12*(-1) = -2 + 12 = 10
(-4) mod 12 = 12-4 = 8 (-4) mod 12 = -4 - 12*[-4/12] = -2 -12*(-1) = -4 + 12 = 8
(-5) mod 12 = 12 - 5 = 7 (-5) mod 12 = -5 - 12*[-5/12] = -5 -12*(-1) = -5 + 12 = 7
反身性 —— a ≡ a (mod m) [ ≡ 恒等于 ]
线性运算定理 —— 如果a ≡ b (mod m),c ≡ d (mod m) 那么:
(1)a ± c ≡ b ± d (mod m)
(2)a * c ≡ b * d (mod m)
所以说一个数的反码,实际上是这个数对于一个模的同余数。而这个模并不是我们的二进制,而是所能表示的最大值。这就和钟表一样,转了一圈后总能找到在可表示范围内的一个正确的数值
补码计算的溢出问题
向最高位的进位和溢出的进位(极高位进位)同时存在或同时不存在时无溢出;如果有一个有进位,则出现了溢出,向最高位进位为正溢出,有溢出的进位为负溢出
只要有溢出,其结果就是错误的,同时对最高位和极高位有进位的,舍去极高位即可
对最高位的进位 | 对极高位的进位 | |
正溢出 | 0 | 1 |
负溢出 | 1 | 0 |
无溢出 | 1 | 1 |
无溢出 | 0 | 0 |
进位实质上就是对应位数的值均为1,二进制中“逢二进一”,所以产生了进位,故只要是两个要相加的整数的高2位有且仅有一对对应都是1,结果就会溢出
对小数的溢出检测——双符号位相同表示未溢出,双符号位不同则表示溢出
双符号位 xx.xxxxxx | |
相同 00.xxxxxx / 11.xxxxxx | 未溢出 |
不同 10.xxxxxx / 01.xxxxxx | 溢出 |
只有同符号数相加才会产生溢出,异号符号数相加则不会溢出
解决溢出的办法
在原码的基础数位上再加一位表示符号位,通过原码,符号位不变,其余位按位取反得到反码,再加1得到补码,补码相加后得到结果的补码,然后减1得到反码,符号位不变,其余位按位取反得到结果的原码