假设我们使用Java中的32位整型来表示2 , 它的十进制是000…010 。最低的两位是10 , 前面的高位都是0 。如果我们使用-2的原码 , 也就是100…010 , 然后我们把3的二进制原码000…011和-2的二进制原码100…010相加 , 会得到100…0101 。具体计算你可以看我画的这幅图 。
二进制编码上的加减法和十进制类似 , 只不过 , 在加法中 , 十进制是满10才进一位 , 二进制加法中只要满2就进位;同样 , 在减法中 , 二进制借位后相当于2而不是10 。
相加后的结果是二进制100…0101 , 它的最高位是1 , 表示负数 , 而最低的3位是101 , 表示5 , 所以结果就是-5的原码了 , 而3+(-2)应该等于1 , 两者不符 。
如果负数的原码并不适用于减法操作 , 那该怎么办呢?这个问题的解答还要依赖计算机的溢出机制 。
我刚刚介绍了溢出以及取模的特性 , 我们可以充分利用这一点 , 对计算机里的减法进行变换 。假设有i-j , 其中j为正数 。如果i-j加上取模的除数 , 那么会形成溢出 , 并正好能够获得我们想要的i-j的运算结果 。如果我说的还是不太好理解 , 你可以参考下面这张图 。
我们把这个过程用表达式写出来就是i-j=(i-j)+(2^n-1+1)=i+(2^n-1-j+1) 。
其中2^n-1的二进制码在不考虑符号位的情况下是n-1位的1 , 那么2^n-1-2的结果就是下面这样的:
从结果可以观察出来 , 所谓2^n-1-j相当于对正数j的二进制原码 , 除了符号位之外按位取反(0变1 , 1变0) 。由于负数-j和正数j的原码 , 除了符号位之外都是相同的 , 所以 , 2^n-1-j也相当于对负数-j的二进制原码 , 除了符号位之外按位取反 。我们把2^n-1-j所对应的编码称为负数-j的反码 。所以 , -2的反码就是1111…1101 。
有了反码的定义 , 那么就可以得出i-j=i+(2^n-1-j+1)=i的原码+(-j的反码)+1 。
【什么是符号位如何让计算机理解哪些是正数 为什么手机要补码呢】如果我们把-j的反码加上1定义为-j的补码 , 就可以得到i-j=i的原码+(-j的补码) 。
由于正数的加法无需负数的加法这样的变换 , 因此正数的原码、反码和补码三者都是一样的 。最终 , 我们可以得到i-j=i的补码+(-j的补码) 。
换句话说 , 计算机可以通过补码 , 正确地运算二进制减法 。我们再来用3+(-2)来验证一下 。正数3的补码仍然是0000…0011 , -2的补码是1111…1110 , 两者相加 , 最后得到了正确的结果1的二进制 。
可见 , 溢出本来是计算机数据类型的一种局限性 , 但在负数的加法上 , 它倒是可以帮我们大忙 。
推荐阅读
- 什么手表跟手冰冰手机
- 苹果手机的拼音是什么
- 捐赠手机有什么讲究吗
- 清明节应该注意些什么 清明节动植物有什么变化
- 清明节的传统有荡秋千、蹴鞠、踏青、放风筝、扫墓等 清明节都有哪些风俗
- 清明节放风筝的来历及习俗 清明节放风筝风俗是怎么形成的
- 三月三日起源于中华民族原始社会的原始制度,相传农历三月初三是 三月三是什么节日
- 三月三的来历和风俗有哪些 关于三月三的美食有哪些
- 广西壮族三月三的食物有哪些 什么是三月三壮族