前面,对补码的介绍,已经比较详细了。
下面列出数值与补码的对照表。
正负数值,存在计算机系统中,就是这个样子的滴!
四位的补码,用处不多,多半都是用在讲解理论的场合。
八位和十六位的,是常用的形式的。大家可关注一下它们的表示范围。
另外,还有 32 位数的补码,限于篇幅,这里就不列出了。
看到了吧:正数的补码,最高位是 0、负数的补码,最高位都是 1。
这个最高位,计算机专家称为 “符号位”,其实,它应该称为 “正负特征位” 更合理。
因为,这个位的值,并非是人为设定的,而是由补码的计算规律,自然生成的。
-----------------------
计算机中的补码,是怎么来的呢?
在计算机教材中,都是连篇累牍的介绍:补码是 “原码取反加一”。
但是,由于原码反码错误定义,在原码和反码中都有两个零!因此,原码和反码,都比补码少一个数字。所以,“原码取反加一”,是有缺陷有漏洞的说法。
例如,字长在 8 位时,-128 就只有补码,却没有原码和反码。
那么,用 “取反加一” 来求-128 的补码,显然就是不可能的。
况且,在计算机中,有原码吗?
没有!
计算机中,不但没有-128 的原码,其它数值的原码,也是不存在的。
因为,在计算机系统中,数值,一律采用补码表示和存储。
所以,计算机中,只有补码,原码和反码,都是不存在的。
那么,拿什么取反?又拿什么加一?
所以说,用 “取反加一” 求补码,也只能是 “纸上谈兵” 而已。
-----------------------
此外,在一些貌似严谨教材中,还介绍了补码定义式:
当 X < 0 时, [ X ]补码 = 模 + X。
但是,这个公式,在计算机中,也是无法实现的。
因为,式中的模,是超出预定字长的。
例如,在 8 位机中,字长为 8。
此时的模,就是:2^8 = 1 0000 0000 (二进制)。
这是一个 9 位的二进制数啊!
你让 8 位机如何计算?
所以说,补码定义式,不过就是画了 “一张大饼” 而已。
-----------------------
那么,计算机中的补码,究竟是怎么来的呢?
按照定义式,[ X ]补码 = 模 + X。
那么,在 8 位机中,用 8 个 0 代替模即可。
实际上,8 位机的模,它的二进制就是 0000 0000 !
那么,当 X 是负数(如-27),按照定义式求 8 位补码,即:
[-27]补 = 0000 0000 + (-27 ) = 0000 0000-27
就是说,求负数 (-X ) 的补码,用二进制计算 “0-X” 即可。
因此有: [-27]补 = 0 - 27
= 0000 0000-0001 1011
= (借位 1) 1110 0101
进位或借位,并不属于八位数,舍弃之。
所以,-27 的八位补码就是 1110 0101。
用这种方法,就可以求出-128 的补码了。
即有: [-128]补 = 0 - 128
= 0000 0000-1000 0000
= (借位 1) 1000 0000
所以有:[-128]补 = 1000 0000。这就弥补了 “原码取反加一” 缺陷或漏洞。
同理,求正数 (+X) 的补码,也就是用二进制计算 “0+X”。
那么: [+27]补 = 0 + 27
= 0000 0000+0001 1011
= 0001 1011
在此处,也就证明了:
零和正数 X 的补码,就是 X 的二进制数形式。
综上,不论 X 的正负,求 X 的补码,都是 “0+X”。这是按照补码定义式推导出来的,没毛病!
那么,在计算机内部,就用二进制按此式计算一下,即可。
计算机中的补码,就是这么弄出来的。
-----------------------
操作者在使用计算机时,可能要输入负数,如:-125。
而实际上输入的是:-、1、2、5、回车,共五个字符的 ASCII 码。
系统软件会先把 1、2、5 的 ASCII 转为二进制数,合并,就得到了正数的二进制:0111 1101。
再根据负号,将其变换为-125 的补码:1000 0011,存入存储器。
看到了吧:
你输入的是负数(负号、绝对值),计算机将由正数(绝对值)变换出来负数的补码。
-----------------------
计算机中的补码(0 + X 或 0-X) ,到底是怎么弄出来的呢?
在小学,学过这些吧: X-X = 0、-X = 0-X。
X 和-X,是一正一负两个数,它们的绝对值相同,它们就称为:相反的数
那么,知道一个数 X (不论正负),用 “0-X” 就可以算出与 X 相反的数。
同样,相反的数的补码,也是 “相反” 的。(注意不是反码。)
因此,知道一个补码,用 “0-X” 即可求出与 X 相反数的补码。
由上述可知,正数 ( X ),存入计算机后,它本身,就是补码了。
而负数 (-X) 则需要经过计算 0-X,才能得到负数的补码。
在 80x86 指令系统中,NEG 指令的功能就是 “0-X”。
利用 NEG 指令,即可实现正负数补码的互相转换。
如:
MOV AL,0111 1101 B ; 给 AL 赋值 125
NEG AL ;(AL) = 1000 0011,即为 [-125]补
NEG AL 的操作,理论上是:0-(AL) → (AL)。
而实际上,则是:AL 中全部的位都取反,再加一。
注意到了吗?
这可不是:符号位不变、数值位取反加一。
在开始学补码时,学的 “取反加一”,是说:符号位不变、数值位取反加一。
但是,在计算机中可没有这种指令啊!
你如果非要这么做,你就必须自己编写一个小程序了。
说到这里,就可以知道,计算机教材上写的:
“负数的符号位为 1,原码取反加一,符号位不变”、
“补码定义式:[ X ]补码 = 模 + 负数” ,
这些求补码的方法,在计算机中,都是无法实现的。
计算机专家编写教材时,都是脱离实际,随便胡嘞嘞一通。
显然,这些专家,肯定都没有见过计算机,呵呵
--本文完--