我一直想搞懂补码这个玩意当初是怎么设计出来的。
比如int型 占4个字节,32位,有正有负,最高位0表示正,1表示负,这是可以理解的,这是正常的设计逻辑,而到了其他位,老师们教的就开始含糊了,直接告诉你,看到高位1就表示是负数,然后对其他位先取反,再+1得到的二进制就是想要的负数。
比如 11111111 11111111 11111111 11111111先求反 00000000 00000000 00000000 00000000 然后+1 得到 00000000 00000000 00000000 00000001 其值为1,然后加上符号就是-1了。
英文中第一次取反叫做one‘s complement(反码),第二次取反叫做 two's complement(补码)。
我一直在想,是谁想出这么变态的设计,让他安安静静的就高位用0,1指代正负,其他跟正数一样不好么?
事实上,郑重想法虽然符合一般人的逻辑想法,但是想必设计者是个美学达人,他觉得以0位分界线,右边应该呈递增形态,左边呈递减形态。
我们不妨先看看0,1,2,3,4,5在二进制中都是怎么表示的:
00000000000000000000000000000000
00000000000000000000000000000001
00000000000000000000000000000010
00000000000000000000000000000011
00000000000000000000000000000100
00000000000000000000000000000101
我们再看看-1,-2,-3,-4,-5是如何表示的:
11111111111111111111111111111111
11111111111111111111111111111110
11111111111111111111111111111101
11111111111111111111111111111100
11111111111111111111111111111011
哇,好像我发现规律了,正数,是1在一堆0里努力的向前跳呀,而负数是0在一堆1中向前跳呀。
是在太激动了!你说当初的大师会不会是这么想的,既然正数是通过一排0刷成1来表示,那么负数为什么不能通过一排1刷成0来表示呢,这样递减性自然就有了。
按照这种思路,11111111111111111111111111111111就该表示0,唔0已经占用了00000000000000000000000000000000 ,那它就表示-1吧,然后第一个0在末尾就该表示-2,以此类推。。。
如果把0和1只看成是一个符号,0也按照1那样去计算2的n次方会是什么情况,只不过要加个符号,也就是计算 -(2的n次方)
利用归纳演绎法,11111111111111111111111111111110 看看-2这个0的位置,在位数0上,我们用0出现的位置计算-( 2的0次方)等于-1,我们知道-1已经有表示,所以让此值跟-1相加,加一起=-2
11111111111111111111111111111101 表示-3,0在位数1上,我们用0出现位置 -(2的一次方)等于-2,跟-1相加等于-3
11111111111111111111111111111100表示-4,出现两个0,-(2^1)+(-2^0)=-3,跟-1相加等于-4
11111111111111111111111111111011表示-5,0出现在位数2上,(-2^2)=-4,跟-1相加等于-5
哇喔,好像根据零计算赋值,而后加个-1也是这个结果。
而我想补码也是这么来的。试想一下,给你一个负值-58,只要0出现的值加一起等于57就好了。也就是如下值。
11111111111111111111111111000110
好了,到此我的理解结束了。不知道大家是否认同。