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,不管是正数还是负数