对于补码的理解,一直以来都觉得太巧合,但又明知这不是巧合干的出来的。这次思考补码的意义中,突然发现之前所做的都是那么白痴。 二进制数就应该从它本身出发来思考,而不是利用各种同余(mod 8)来”验证“(分类讨论最没意思了)。 (以下均用4位二进制数来描述) 对于二进制,我们知道它的符号位是最高位,因此我们就把它当做,正数无可厚非就是本身,负数的话除了数值本身要加8。(即将最高位变成1,这里因为是4位二进制数,所以是+8 ) 补码又是什么呢?正数补码不变,负数补码是符号位不变,其余位取反+1,比如-a,其原码按上述含义来说就是 8+a,反码就是8+(7-a) = 15-a,补码就是相当于 8+(8-a) = 16-a,可以证明。 举个例子来说明这样理解的好处。(0<=a<8, 0<=b<8) a – b = a + (-b) =(补码) a + (16 – b) = 16 + a – b (当然这里放在4位二进制下都需要mod 16 , 由于16 + a – b 可能<16所以不能直接去掉16) 而 8 < 16 + a – b < 24 若a – b >= 0 ,则 16 + a – b (mod 16) = a – b,故刚好就是正确值 若a – b < 0 , 则 16 + a – b (mod 16) = 16 + a – b ,求反补码,16 - (16 +a – b )) = b – a 正确。 说了这么多,貌似还是只是验证补码的正确性。 其实设置补码的原因,我想应该是负数的表现形式的局限,我们只是用补码来代替负数,或者说只是负数的另一种表示方法而已,其本质是不改变的。 举一个例子来说明补码的”本质”? 我们有一个水桶,它的容积是2V,但是我们只用下面部分的V的体积表示水的体积,上一部分V的体积用来表示“欠”多少水的体积。是通过以下方式来表示的,如果欠K体积的水,就用2×V-K 体积的水来表示。 这样我们每次求用A体积的水来还补偿欠B体积的水后还剩下C体积水时(A -B=C),只要把两个水桶的水倒到一起(2×V-B+A),溢出的那一部分就是剩下的C体积的水,而如果没有溢出的话,说明欠的水你还不上,水桶中的水为(2 × V – B + A = 2 × V – (B – A )),说明你还欠B – A 体积的水。 而这种欠水的计算方式设计的就是相当巧妙了。 最后还是不能想出是怎么想出这种方式的,不过就是有牛人想出来了。