通过一道数值转换题重温计算机补码
问题
昨天同事和我聊了他偶然间看到的一道面试题,引出了后面的深入分析。
|
|
为什么输出是 65535 而不是 -1 呢?
分析
先回顾一下计算机相关的知识点:
原码(True form)
原码是指一个二进制数左边加上符号位后所得到的码,且当二进制数大于0时,符号位为0;二进制数小于0时,符号位为1;二进制数等于0时,符号位可以为0或1(+0/-0)。 –维基百科
原码根据符号位能很直观的看出是正数还是负数,但是对于计算机运算来说却不是那么好用了,比如:
|
|
所以如果有负数使用了原码运算,那还得把符号位撇开,这就增加了使用成本,为了解决这个问题就出现了反码。
反码(ones' complement),也叫一的补码
将二进制数每个数字反转,得到的数即为原二进制的一的补码(英语:ones' complement)。若某一位为0,则使其变为1,反之亦然。
- 一的补码以有符号比特的二进制数定义。
- 一的补码是有符号比特的二进制数。
- 正数和0的一的补码就是该数字本身。–维基百科
反码能解决负数运算的问题吗,可以,但是又会出现负零和循环进位的问题。举例:
|
|
对于 0 来说正负并没有意义, 而且还会有反码 0000 0000 和 1111 1111 这两种 0 的表现形式,在使用反码运算时判断是否为 0 还需要考虑这两种情况,为了解决这个问题就又出现了补码。
补码(2’s complement)
正数和0的补码就是该数字本身。负数的补码则是将其对应正数按位取反再加1。
补码系统的最大优点是可以在加法或减法处理中,不需因为数字的正负而使用不同的计算方式。只要一种加法电路就可以处理各种有号数加法,而且减法可以用一个数加上另一个数的补码来表示,因此只要有加法电路及补码电路即可完成各种有号数加法及减法,在电路设计上相当方便。
另外,补码系统的0就只有一个表示方式,这和反码系统不同(在反码系统中,0有二种表示方式),因此在判断数字是否为0时,只要比较一次即可 –维基百科
补码有一个原则:数字a的补码为 -a,举例:
|
|
解答
上面的问题可以拆分成下面的代码便于分析
int(32-bit) 转 char(16-bit) 会失去精度
|
|
扩展
溢出
符号扩展与零扩展
循环进位
- 原文作者:浮华生
- 原文链接:https://www.ahianzhang.com/post/summary14/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。