位运算

来源:互联网 发布:ac尼尔森数据 编辑:程序博客网 时间:2024/05/18 22:40

我们知道位运算是将数字转换成二进制一位一位的进行操作,包括左移(<<)右移(>>)无符号右移(>>>),与(&)或(|)取反(~)异或(^)等等。
下面介绍一下它们:

左移(<<):

举个例子:1<<3,将1左移三位,1的二进制表示为0000 0000 0000 0000 0000 0000 0000 0001,左移三位,变成0000 0000 0000 0000 0000 0000 0000 1_ _ _最后三位空出了,规定补零,最终结果:0000 0000 0000 0000 0000 0000 0000 1000,转换成十进制就是8,也就是扩大了2^3,扩大了8倍。
对于负数的左移和这个原理一样,比如将-1<<3,将-1左移三位,计算机中负数是采用的补码的方式储存的,-1的补码是1111 1111 1111 1111 1111 1111 1111 1111左移三位补零1111 1111 1111 1111 1111 1111 1111 1000,这就是-8的补码,所以-1<<3得到的值为-8
所以左移几位相当于扩大了2的几次幂,正负数通用。

右移(>>):

右移就是将数的二进制形式右移,比如-1>>3,_ _ _1 1111 1111 1111 1111 1111 1111 1111,最高位空出来了三位,用符号位补满,因为-1的符号位为1(代表负数),所以最高三位补1,得到1111 1111 1111 1111 1111 1111 1111 1111还是-1的补码,值还是-1,所以-1不管右移几位还是-1。

无符号右移(>>>):

无符号右移就是右移后对高位空出来的不管是正是负,一律用0补满。在java和javascript中都有,但是c++中并没有这个运算符,可以把树转换成无符号的数然后进行右移操作
代码如下

int num = -4;int res = unsigned)num >> 3;

对于有>>>运算符的

int num = -4;int res = num >>> 3;

两者的结果是一样的

与(&):

与运算是按位相与,其中只有同时为1才为1,否则为0,比如3 & -1 转换成二进制
0000 0000 0000 0000 0000 0000 0000 0011 &
1111 1111 1111 1111 1111 1111 1111 1111每位相与
0000 0000 0000 0000 0000 0000 0000 0011所以结果为 3

或(|):

与运算是按位相与,其中只有同时为0才为0,否则为1

取反(~):

取反就是将所有位取反,0变成1,1变成0,是一元运算符,注意的是取反并不是取得相反数,而是比相反数小一的数,比如~-3 = 2,~2 = -3

异或(^):

异或操作:每位如果相同就取0, 否则就取1

位运算的操作都不会改变原数值,而是返回一个结果

比如:

int a = 1;int res = a >> 1;a == 1//trueres == 0// trueres = a & 0x0000;a == 1;//trueres == 0//true

如果原来的数值也改变,可以用 a >>= 1(等价于 a = a >> 1)此类的方法写。

1 0