二进制位运算

来源:互联网 发布:java性能优化 编辑:程序博客网 时间:2024/05/21 17:37

http://blog.csdn.net/gzu_imis/article/details/20078479

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 按位右移 >>

往右边移动几位,左边补符号位( 负数右移高位补1,正数右移高位补0;负数、正数左移低位补0),即正数右移3位,那么左边补3个0,负数右移3位,则左边补3个1


2.6 不带符号右移 >>>

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

原创粉丝点击