众所周知,计算机使用的是二进制数。 和我们惯用的十进制,确实是有点区别的,有人借题发挥吧,说什么机器数、真值。 其实,二进制数与十进制数,并无本质的区别。 在进行算术运算(加减乘除)时,它们都是数。 二进制数本身,它就是真值,并非是什么原码反码补码,更不是什么无符号数、有符号数。
无论什么进制,数,就是数。 谁见过:十进制数中有符号位? 没有。 二进制数,当然也没有。
八位二进制数,称为一个字节,其范围是:0000 0000 ~ 1111 1111。 相当于十进制数:0 ~ 255。 2 个字节的表示范围就是:0000 0000 0000 0000 ~ 1111 1111 1111 1111。 对应的十进制数,大家都会算。
一台计算机,其处理器每次操作所处理二进制数的位数,称为:字长。 字长是多少位,计算机就按照多少位来操作,即不会多一位,也不能少一位。
字长,一般是 1 个字节、2 个字节、4 或 8 个字节。 由这些处理器为核心的计算机,就分别称为:8 位机、16、32、64 位机。 位数多了,再用二进制数表示,就显得眼花缭乱了,所以,高位数的数值,一般都用 16 进制数表示。
为了简明起见,还是用 4 位二进制数来说说吧,半个字节,也是很有代表性的。
4 位数二进制的范围是:0000 ~ 1111。
与其等效的十进制数是:0 ~ 15。
4 位数加上 4 位数,可能会出现进位 1,这个 1 就是:2^4 = 16。
在这 4 位数中,既没有小数点,更没有符号位。
而且,不仅是这 4 位数,就是在整个计算机中,也没有一个小数点,也没有符号位。
没有符号位? 这是不是就是计算机教材中所说的 “无符号数” 呢? 有可能。
更准确说,它们都是【自然数(0 ~ ∞ )】,即,都是:零和正数。
计算机中,有一个加法器,其运算规则就是:逢二进一。
(当然,减法器、乘法器、除法器,与或非异或门也都是有的,暂且不提就是。)
拿两个 4 位数,做个加法运算吧。
二进制数的算法,和十进制的算法无异,可以列出竖式如下:
0 1 0 1 = 5
+1 1 1 1 = 15
------------
进 1、0 1 0 0 = 16 + 4 = 20
这就是 “无符号数” 的加法: 5 + 15 = 16 + 4 = 20。
计算完全正确! 在计算机中,也就是这么算的。
但是,如果你忽略了进位呢? (或者说:故意舍弃了进位。)
你就少算了 2^4 = 16 !
那么,此时的运算,就是: 5 + 15-16 = 5-1 = 4。
式中的 +15,就相当于-1 了!
为什么是-1 ?
因为你:舍弃了进位,少算了 16。
所以有:+15-16 = -1。
加法的竖式,依然如下:
0 1 0 1 = 5
+1 1 1 1 = 15 (-1)
-------------
忽略、0 1 0 0 = 4
怎么回事? 此时,怎么就是【减法运算】了?
你看吧,明明是,两个 “无符号数” 相加,
丢了进位,这就变成了 “有符号数” 相减!
由此可知,数,就是数。 哪有什么 “有符号数、无符号数”? 它们就是同一个数!
同一个数,为什么会有不同的表现?
其实,这并不是二进制数的事,其原因,在外部!
如果,在计算时,舍弃了进位,它就是负数,反之,它依然是原来的数值。
在十进制数的计算中,也有雷同的现象,你看吧:
27 + 99 = (一百) 26
27-1 = 26
如果你舍弃了进位 100,那么,+ 99 就等效于 -1。
看到问题的关键了吗? 是:算法!
数,还是那个数。 因为,你采用了不同算法,数,才有不同的表现。
算法,才是计算机的灵魂!
综上所述,舍弃了进位之后:
正数,就能当负数使用! 计算机专家,据此,就发明了补码。
加法,也就完成了减法运算! 因此,计算机中,就不用安装减法器了。
你看吧,偷了一点懒,就得到了这么大的好处。 真值得好好吹一吹呀!
当然,吹嘘的时候,可不能说偷懒的事,一定得编造一套非常神秘的说法。
机器数真值无符号数带符号数原码反码正负零取反加一符号位也参加计算 ...
没事就多走两步呗!
前面说过,忽略进位一百(100)时,+99,就可以当做-1 使用 。
它们的关系式,显然是:+99 = 100-1。
移一次项,就可以写成:99 + 1 = 100。
看这个式子,怎么觉得,很眼熟呢?
在小学的知识点中,有个概念,叫做:【补数】。
是说:若两数之和是 10、100、...、10^n,这两个数,就是【互为补数】。
因此,在两位十进制时,有:99 和 1、98 和 2、... ,它们都是互为补数。
把小学的知识--补数,推广到计算机领域吧。
计算机用的是二进制,这是唯一的区别。 把原来的 10^n,改成 2^n,即可了。
那么,前面说过的,+15 能够代替-1,就可以用这个式子来计算了:
+15 = 2^4-1。
同理,还有:+14 = 2^4 -2。
其它,以此类推吧。
由这个小学的知识(补数),改动一个进制,就推出了:补码。
在计算机教材中说:补码,是它们如下定义的!
当 X < 0,(即 X 是负数),则有:[ X ]补 = 2^n + X。
它们只字不提小学算术课的知识。
这也难怪,说到小学知识,恐怕这些专家也没有几个人是学过的。
当 X >= 0,(即 X 是正数),也是可以用同一个式子表示的:[ X ]补 = 2^n + X。
只是在此时,正数,加上 2^n,立即就出现了进位。
进位,当然应该舍弃,那么就可以简化为:[ X ]补 = X。
因此,就可以说:零和正数的补码,就是它们自身。
这就是说,无论 X 是正数、负数或零,补码定义式都是同一个,即:
[ X ]补 = 2^n + X。
根本就不必分别定义。
看懂了补码的来源和存在意义,就足够了。
不就是舍弃进位吗! 这有什么难理解的!
因此,所谓的:机器数真值符号位原码反码取反加一符号位也参加运算 ...,就都别提了。
只要知道:计算机中只有二进制数,做算术运算时,二进制数,也是数,加减乘除,就像十进制一样计算,就行了,不用想的太多。
补码,有自己的定义式。 这就是说:补码,与原码反码,并无半点关系。 原码反码中有符号位,就让它们自己留着吧,不要传染到补码这里。 因此,也就可以说:补码并没有符号位,补码的全部位,都是数值位。 事实也确实是如此,补码的最高位,是可以参加运算的,如果是代表正负号(+-),哪还能运算哪! 实际上,补码的最高位,只是正负的特征位而已,并非是由某个人规定的符号位。
例如:求-31 的八位补码是什么?
解: 2^8-31 = 256-31 = 225 = 1110 0001 (二进制补码)。
完事! 根本就不用通过原码码来转换。
另外,求补码,还有一个简便方法:【减一取反】。
即,先减一: 31 -1 = 30 = 0001 1110 (二进制)。
再取反,就得到了-31 的补码: 1110 0001。
由补码求它代表的十进制数,当然也可以用定义式,反过来做。
但是,这里也有一个简便算法,即:补码首位的权,是个负数。
一般的八位二进制数,各个位的权,分别是:
128、64、32、16、8、4、2、1。
如果是八位的补码,各个位的权,就分别是:
-128、64、32、16、8、4、2、1。
例如,有一个补码是:1110 0001,
它代表的十进制数是:-128 + 64 + 32 + 1 = -31。
换一个,一个补码是:0110 0001,
它代表的十进制数是: 0 + 64 + 32 + 1 = +97。
只要学会【进制转换】,各种问题,就都迎刃而解了。
以上是个人浅见,不值得相信,看过的,笑一笑就完了。
--本文完--