谈谈补码与移位

在计算机中整数的表示使用补码来表示的。

什么是补码呢?首先要明白什么是原码。

数字是有符号的,计算机中,用最高位作为符号位。以四位机器码举例:1的原码表示是:0001; -1 的原码表示是:1001。

也就是说表示实际数值的只有3位。因此4位机器码原码表示数的范围是:[-7, 7],其中0有两种表示,+0:  0000; -0:   1000。

原码表示清晰易懂,但对机器来说却是个麻烦,因为我们必须设计两套电路分别表示加法和减法。

为了统一加减法电路,人们想到了同余原理,让符号位也参与运算,补码应运而生。(反码没有实际应用,没必要记,这里就不解释了,实际上如果不是为了引出正数的补码表示,原码也没必要记)

对于正数,补码表示就是其原码,还以四位机器码举例:1的补码表示是:0001。

对于负数,补码表示就是对于相应的正数表示,连同符号位一起,各位取反后加1。 -1的补码表示为: 1111。(0001 各位取反,1110, 再加1)

对于补码来说,我们没办法直接看出负数的值,想知道负数的真值,我们需要对负数求补,再加上符号位即可。

以-3举例:1101。最高位是1,我们知道它是个负数。对其求补:0010 + 1 = 0011。我们也就知道了其值为-3。

也就是说,正数求补就是其对应的负数,负数求补就是其对应的正数。

对于减法,加上其负数的补码即可。我们成功的把减法运算变成为了加法运算。(不理解同余原理的,可能难以理解。记住结论即可,我不详细展开介绍了)

对于4位机器码来说,补码表示范围为:[-8, 7]。这里0只有一种表示:0000. 所以比原码多表示了一个负数:-8 : 1000。+8的补码为 01000,由于溢出的原因,无法表示。

下面给出8位机器码表示的几个数字的补码:

0           0000 0000

1           0000 0001

2           0000 0010

... ...

127       0111 1111

-1          1111 1111

-2          1111 1110

... ...

-128      1000 0000

 有了补码之后,计算机中的加减乘除都可以用加法和求补电路实现,大大简化了电路设计。

下面谈谈移位。这里不多谈,就只谈谈java中的移位操作。

java这种语言竟然有移位操作,确实出乎人意料。不过考虑到java设计初衷是用于嵌入电视机机顶盒的,有这种面向底层的操作倒也不奇怪。

谈到移位,不得不提位运算符 | 或;  & 与; ^ 异或; ~ 取反。

这四种都是按位执行,也很简单,不详细展开。记住异或,异1同0即可。

java中左移 << :  高位舍去,低位补0。相当于乘2,当然前提是不溢出。 

java中右移 >>: 正数补0,负数补1,低位舍去。相当于除2,易知正数右移,最小得0;负数右移,最小得-1。

上面两种移位操作,称为算术移位,因为它们保存了算术符号,这与C C++是一样的。(左移在不溢出的情况下,符号是不会变化的。不过要注意溢出的发生。)

java中还有一种逻辑右移:>>> , 无论正负,高位补0,低位舍去。这是C C++ 没有的。

想要查看二进制表示,可以调用Integer.toBinaryString(int i)方法。

原文地址:https://www.cnblogs.com/zqiguoshang/p/6553181.html