深入理解补码

一次byte变量运算

b3的值为多少?

byte b1 = 127;
byte b2 = 1;
byte b3 = (byte)(b1 + b2);

结果为-128。

对于无符号位的byte类型变量可以表示的数值范围为0 ~ 255(0 ~ 2^8-1),可以表达的数值的个数是256个,即2^8个。

有符号位则为-128 ~ 127(-2^7 ~ 2^7-1),且最高位(第八位)通过0为正数,1为负数来表示数值的正负。可以表达的数值的个数也是256个,即2^8个。

正常来说,127的二进制为0111 1111,1的二进制为0000 0001。相加之后应为1000 0000,即128,为什么是-128?
这也说明在java中默认是有符号位存储变量值的。也应当如此,除非手动声明类似 unsigned 这样的变量修饰符。那么为什么会得出-128呢?先再次复习一下补码的知识。

补码

如何推算补码,例如:

  1. 127(正数原反补码都一致)

    1. 原码: 0111 1111
    2. 反码: 0111 1111
    3. 补码: 0111 1111
  2. -1

    1. 原码: 1000 0001
    2. 反码: 1111 1110 (除符号位都取反)
    3. 补码: 1111 1111 (反码+1)

可以发现一个规律,可以直接对负数的绝对值取反+1得出补码,因为绝对值一定为正数,最高位一定为0,取反时直接对全位数取反结果不会出现问题。

如何通过补码推出实际表示的值(对上面的操作步骤逆操作即可,只演示负数):

例:-1

  1. 补码: 1111 1111
  2. 反码: 1111 1110
  3. 原码: 1000 0001

为什么要使用补码

知道了补码的推算后,那么为什么要使用这种方式?见下面的例子。

-1 + 1
1000 0001
0000 0001
---------
1000 0010 (-2)

-2 + 2
1000 0010
0000 0010
---------
1000 0100 (-4)

正常的进制运算,结果是不正确的。但我们将其都转为补码后:

-1 + 1
1111 1111
0000 0001
---------
0000 0000 (0)

-2 + 2
1111 1110
0000 0010
---------
0000 0000 (0)

-3 + 2
1111 1101
0000 0010
---------
1111 1111 (-1)

结果正确了。为什么会这样?这就是精妙之处,利用进位溢出。当正常的进制运算无法得出正确结果时,不妨换个角度思考,例:

-1 + 1
.... ....
0000 0001
---------
0000 0000 (0)

-1的进制码为多少时,结果为0呢:1111 1111
1111 1111如何得出的呢:绝对值的进制码取反+1

回顾问题

为什么最后的结果是-128,可以推算:

127 + 1
0111 1111
0000 0001
---------
1000 0000

补码1000 0000实际对应的值是多少呢?
补码: 1000 0000
反码: 1111 1111
原码: 1000 0000 (-128)

感觉好像不太对,1000 0000是不是为-0?为什么是-128?详细可以看链接,下面引入文章片段:

0 111 1111   127
0 000 0010   2
0 000 0001   1
0 000 0000   0
1 111 1111  -1
1 111 1110  -2
1 000 0001  -127
1 000 0000  -128

在原码和反码表示法中,0有两种表示方式,分别为正0(0000 0000)和负0(1000 0000/1111 1111)。然而在正常的算数中,0是不应该有符号的。
补码表示法则没有这种区分,不论正0还是负0都会表示为0000 0000(负0取反加1丢掉溢出位后也是这个结果),所以补码正好能用1000 0000多表示一个数。
根据上述补码表格中“递减”的规律,把1000 0000放在-127的后面,表示-128正合适(1000 0000 + 0111 1111 = 1111 1111 = -1),也符合符号位为1表示负数的惯例。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值