http://blog.csdn.net/wuxiaobingandbob/article/details/20150737

1.原码 反码 和 补码
二进制位元算包括按位与、按位或、按位异或、取反、左移以及右移这几种运算,运算都使用补码,结算的结果也是补码

如果其他进制,比如最常见的十进制要进行二进制位运算,那么先得把十进制数转成二进制数

在了解二进制位运算之前,就要先掌握进制转换,那么先来复习一下几个概念:原码、反码、补码

以下我们假设整数均用1个字节表示,1个字节即8个二进制位

1.1 原码

计算机对数字的二进制表示,原码使用最高位表示符号位:0表示正数,1表示负数,比如

0 0 0 0 1 0 1 1 =====》 表示正数 11

1 0 0 0 1 0 1 1 =====》 表示负数 -11

原码的缺点是:不能直接参与运算

比如上述 11 + (-11) 结果应该为 0 才对,但是如果我们把二进制直接相加(注意逢2进1)

1 0 0 1 0 1 1 0 =====》 表示负数 -22

很明显不对,所以为了表示正确的计算,又定义了反码和补码的,参与运算的都是补码

1.2 反码

把每个二进制位取反,即0变成1,1变成0,但是符号位保持不变

只不过:正数的反码和原码一样,没有任何变化,那么我们来看下 -11 的反码是怎么表示的

(1)先看 -11 的原码,得到 1 0 0 0 1 0 1 1 =====》 -11 的原码

(2)每个二进制位取反,符号位不变,得到 1 1 1 1 0 1 0 0 =====》 -11 的反码

1.3 补码

【反码 + 1】 就得到补码,不过正数的补码和原码也是一样的,没有任何变化,那么我们来看 -11 的补码是如何表示的

(1)-11 的反码已经计算出来 1 1 1 1 0 1 0 0 =====》 -11 的反码

(2)+1 的操作,注意逢二进一,得到结果是 1 1 1 1 0 1 0 1 =====》 -11 的补码

好了,我们再来看下 11 + (-11) 的操作,注意前面已经说过,都使用补码的计算

0 0 0 0 1 0 1 1 =====》 正数 11 的补码

1 1 1 1 0 1 0 1 =====》 负数 -11 的补码

===========================================

0 0 0 0 0 0 0 0 =====》根据逢二进一的相加操作,得到结果就是 0 ,这和我们预期结果相同

之前说过运算使用补码,并且计算结果也是用补码,那么拿到补码之后,怎么还原成十进制数呢?

对于正数而言,因为反码和补码都是相同的,所以一个补码,比如 0 0 0 0 0 0 1 1 ,很明显:十进制数就是 3

对于负数而言,【反码 + 1】 = 补码 所以推导出来 【反码】 = 【补码 - 1】,所以上述补码计算的反码结果为

1 1 1 1 1 1 0 0 ,那么得到反码了,原码就很简单了,直接取反即可,符号位还是保持不变,最终得到

1 0 0 0 0 0 1 1 , 这样我们很明显看出来,十进制数就是 -3

2.二进制位运算
已经了解原码、反码和补码的概念了,并且也了解二进制运算使用补码,结果也是补码

那来看一下二进制位运算的规律

2.1 按位与 &

1 & 1 结果等于1,其他结果为0,你可以把这个看做boolean类型的 && 运算,只有都为真,结果才为真

2.2 按位或 |

0 | 0 结果等于0,其他结果为1,你可以把这个看做boolean类型的 || 运算,只有都为假,结果才为假

2.3 按位异或 ^

0 ^ 0 结果等于0

1 ^ 1 结果等于0

0 ^ 1 结果等于1

1 ^ 0 结果等于1

因此,相同异或结果为0,相异异或结果为1,你可以把这个看做异性相吸吧。。。

2.4 按位取反

这个最简单,就是1变0,1变0

比如 7 的二进制表示是 0 0 0 0 0 1 1 1

那么 ~7 按位取反之后 1 1 1 1 1 0 0 0

再次提醒,二进制位运算的结果是补码,不要把上面计算结果搞成原码哦

所以,反码 = 补码 -1 ,得到 1 1 1 1 0 1 1 1 我想逢二进一你会计算,借位想减你应该会

所以原码就是反码取反呗, 1 0 0 0 1 0 0 0 这才对到 -7 取反的结果,就是 -8

没有错,为什么这么巧呢,7取反的结果就是 -8 ,其实 10 取反的结果就是 -11

那么负数呢,那就反过来,比如 -11 取反的结果就是 10

2.5 按位左移 <<

往左边移动几位,右边就补几个0,正因为是右边补0,而我们知道符号位在左边,所以右边如果有1移到符号为了,结果就产生负数了

比如 7 的二进制是 0 0 0 0 0 1 1 1

那么 7<<2 表示要左移两位 0 0 0 1 1 1 0 0 结果是 28

你发现 7 4 = 28 了吧,因为左移几位,就是把【原来的数 2的位移次指数】

右比如在Java里面, Integer.MAX_VALUE << 1 就是拿最大正数在往左移,就发现结果为 -2 了

2.5 按位右移 >>

往右边移动几位,左边补符号位,即正数右移3位,那么左边补3个0,负数右移3位,则左边补3个1

2.6 不带符号右移 >>>

不带符号右移,就是左边全补0,不管是正数还是负数