虽然不知道大牛怎么想到这样解决补码的正负表示问题1,但这种解决办法的正确性倒是可以尝试证明一下。
首先需要明确什么叫正确性,充要条件暂时没有想到,先列举几个必要条件,至少这些条件需要能成立:
本身的值表示正确本身的符号表示正确运算结果的值表示正确运算结果的符号表示正确
接下来证明每一个条件:
本身的值表示正确、运算结果的值表示正确
一定正确,左边加一位对值来说是完全不影响的,可以从两个角度分析
左边加1就等于加了一个模左边是高位,本身的运算只会向高位进位,完全不会影响低位的运算
本身的符号表示正确
只要用这个符号系统表示,就会自然正确
运算结果的符号表示正确
没想到好办法,只能分情况讨论。
假设一个具体的情形方便举例:4位二进制,1位符号位,模是8,使用补码的表示范围是-8~7。另外把数学数字运算的结果称为「数学结果」,把通过这种位算法运算的结果称为「位运算结果」,这两个结果的符号一致就表示正确。根据符号位是否会受值位运算的结果影响分为两大类,其中又根据具体情况细分。
1)值的位运算不溢出
两个正数 符号一致
数学结果:两个正数相加还是正数,符号一定为正位运算结果:因为值的位运算不溢出,两个0相加还是0,也就是正两个负数 情况不存在
数学结果:符号一定为负位运算结果:值的位运算不溢出,两个1相加进一位得到0,也就是正看起来两个结果的符号一定不一致。但其实可以证明这种「值的位运算不溢出」情况下「数学运算结果一定溢出」,而数学运算结果溢出的情况不用考虑,我们不保证这种情况下运算结果的正确性证明:
假设负数A的补码表示是
[1a1a2a3]
,它的数学大小
=−8+(a1∗22+a2∗2+a3)
,设右侧为
A
,那么数学大小
=−8+A
假设负数B的补码表示是
[1b1b2b3]
,它的数学大小
=−8+(b1∗22+b2∗2+b3)
,设右侧为
B
,那么数学大小
=−8+B
那么“值的位运算不溢出”这个条件用数学表示就是
A+B<8
这时候计算数学运算结果:
−8+A−8+B=−16+A+B
,因为
A+B<8
,所以这个结果一定小于
−8
,而它的表示范围是
−8 7
,所以溢出了一正一负
正数绝对值大于负数 情况不存在
数学结果:正位运算结果:0和1相加得到1,也就是负虽然结果不一致,但是可以证明这种情况不存在,也就是「正数绝对值大于负数」时「值的位运算一定溢出」证明:
假设正数A的补码表示是
[0a1a2a3]
,它的数学大小
=a1∗22+a2∗2+a3=A
假设负数B的补码表示是
[1b1b2b3]
,它的数学大小
=−8+(b1∗22+b2∗2+b3)=−8+B
「正数绝对值大于负数」的数学表示是
A−8+B>0⇒A+B>8
「值的位运算」结果为
A+B
,它一定大于8就说明溢出了正数绝对值小于负数 符号一致
数学结果:负位运算结果:0和1相加得到1,也就是负正数绝对值等于负数 情况不存在
位运算结果需要是0,而如果值位不溢出,符号一定为负,其实通过「正数绝对值大于负数」这个证明可能看出,正数绝对值等于负数时值位也一定溢出
2)值的位运算溢出
两个正数 情况不存在
两个正数的值位运算溢出意味着运算结果大于8,意味着数学运算结果溢出,不考虑两个负数 符号一致
数学结果:一定是负的位运算结果:两个1相加是0,但是有进位,如果进位为1就没问题,那进位会不会是2呢?不会,因为后三位最大是7,两个7是14,不超过16,所以结果也是负数一正一负
正数绝对值大于等于负数 符号一致
数学结果:正位运算结果:0和1相加得到1,溢出1位得到0,也就是正正数绝对值小于负数 情况不存在
数学结果:负位运算结果同上,为正但这种情况不存在,也就是「正数绝对值小于负数」一定不「值的位运算溢出」证明
假设正数A的补码表示是
[0a1a2a3]
,它的数学大小
=a1∗22+a2∗2+a3=A
假设负数B的补码表示是
[1b1b2b3]
,它的数学大小
=−8+(b1∗22+b2∗2+b3)=−8+B
「正数绝对值小于负数」数学表示是
A−8+B<0⇒A+B<8
,说明值的位运算一定不溢出
总结以上对于「运算结果的符号表示正确」的证明,所有存在的情况中,符号都是一致的,所以运算结果的符号表示也是正确的。
结论
综上所述,4个条件均成立,所以从目前来看,补码的正确性是可以保证的。
见计算机中整数为什么以「补码」的形式存储? ↩