学到C语言的本质之补码时(http://learn.akae.cn/media/ch14s03.html)。发现不是很理解,特别是这段描述。
如果8个bit采用2‘sComplement表示法,
负数的取值范围是从10000000到11111111(-128~-1),
正数是从00000000到01111111(0~127)。
于是搜索了不少资料,总算理清了这一点。
首先,原码,反码,补码是一个真值用二进制表示的的不同方式。将一个真值表示成二进制字串的机器数的过程就称为编码。无符号数没有原码、反码和补码一说。只有带符号数才存在不同的编码方式。
至于为什么计算机最终选择补码来表示呢?具体看这里
http://sharecourse.upln.cn/courses/c_809_04/theory/module_2/pdf/whybm.pdf
从原码转成补码也看上面的文章。
这里有一点很重要的,就是从补码怎么转为原码或者真值呢?
其实这个过程跟从原码转成补码是一样的。这一点很多学习资料都没提到。我是在
http://wenwen.soso.com/z/q110390792.htm这里看到的。
具备了以上知识后,现在来解释一下补码的范围是怎么回事。
1 先从简单的开始,正数的范围,明显补码的二进制范围是从00000000到01111111。那么取几个特殊的值来看看,
0000,0000
0111,1111
这两个二进制的数是谁的补码呢?
也就是(0000,0000)的真值是?
(0111,1111)的真值是?
由于正数的补码跟真值是一样的,
所以(0000,0000)的真值是0,(0111,1111)的真值是127。
由此可见,用补码来表示正数,取值范围是0-127。
2 负数的范围,明显补码的二进制范围是从10000000到11111111。再取几个特殊值来看看,
那么10000000的真值是?
10000001的真值是?
11111111的真值是?
上面有说过如何从补码转为真值。
计算后,发现
10000000的真值是(-1000,0000)=-128
10000001的真值是(-111,1111)=-127
11111111的真值是(-000,0001)=-1。
所以用补码表示负数,范围是-128到-1。
这里,特地,演算一下。(采取先不管符号位的做法)
10000001(这是补码)
取反,得 (111,1110)
+1,得(111,1111)
加上符号位(-111,1111)即-127
(1000,0000)(这是补码)
取反,得(111,1111)
+1,得(1000,0000)
加上符号位,得 –1000,0000,即是-128。
那么我们验证一下真值-127的补码形式是不是(1000,0001)。
-127这是真值,即(-111,1111)
转为原码(1111,1111)
取反,转为反码(1000,0000)(符号位不变)
+1,(1000,0001)(符号位不变)
再验证一下真值-128的补码形式是不是(1000,0000)。
-128(-1000,0000)显然原码表示不了。
只能这么理解法,
先不管符号位,得(1000,0000)。
取反,得(0111,1111)
+1,得(1000,0000),7位溢出了,去掉进位得(000,0000)
补上符号位得(1000,0000)。
其实,我们只要记住真值-128的补码形式是(1000,0000)就好了。
其实,求反加1的方法是有缺陷的,并不是补码的定义,了解了补码的定义,才可以真正了解补码与真值的转换。
就是利用同余。http://sharecourse.upln.cn/courses/c_809_04/theory/module_2/pdf/whybm.pdf
在数学中,用“同余”概念描述上述关系,即两整数 A、B 用同一个正整数 M (M 称为
模)去除而余数相等,则称 A、B 对 M 同余,记作:
A=B (MOD M)
具有同余关系的两个数为互补关系,其中一个称为另一个的补码。当 M=12 时,-
5 和+7,-4 和+8,-3 和+9 就是同余的,它们互为补码。
从同余的概念和上述时钟的例子,不难得出结论:对于某一确定的模,用某数减去
小于模的另一个数,总可以用加上“模减去该数绝对值的差”来代替。因此,在有
模运算中,减法就可以化作加法来做。
可以发现,有个技巧,互为补码的两个数加起来刚好等于模。
对于8位得二进制数,模等于2的8次方=256。
真值-127的补码是谁呢?
-127等价于 加上模减去127的差,即加上 129(1000,0001)。
因此-127与129(1000,0001)互补。
即真值-127的补码为(1000,0001),这个补码看起来是正数,其实表示的是负数。
现在再来看看真值-128的补码形式是不是(1000,0000)。
显然,-128等价于加上 256-128=128,即(1000,0000)。
触类旁通,真值-126的补码是?
-126等价于加上256-126=130,即(1000,0010)。
上面是,由真值求补码。
那么怎么由补码求真值呢?
比如补码(1000,0010)的真值是?
显然(1000,0010)=130,符号位是1,表示的真值是负数,
130-256=-126。
补码(1000,0000)的真值是?
显然,(1000,0000)=128,符号位是1,表示的真值是负数,
128-256=-128。
夜已深,先了解到这一步,以后有更深入的理解再来总结更新。