有趣的位运算

位运算


位运算,即是 操作二进制的bit(位),来进行运算。

其分类有:按位与(&),按位或(|),按位异或(^),按位取反(~),按位左移(<<),按位右移(>>)

java中还有 “无符号右移” (>>>);C语言中是没有的

参与位运算的,应该是一个整数,或者字符型(其实质内部也是对应一个整数)

按位与(&)


按位与,是双目运算符。其功能是参与运算的两数各对应的二进位相与。只要对应的二个二进位都为1时,结果位就为1。参与运算的两个数均以补码出现。

。。。 上面说的太长了, 我都记成: 同位为1值为1,反之为0

  • 获取某一段的8位

    比如int类型,在当前系统中占用4个字节,1个字节等于8bit(位),即占用32位

    从右数,想获取第一段的8位: a&0xff; 获取第二段的8位:(a&0xff00)>>8; 第三段则右移16位,第四段则右移24位。 因右移的优先级高,所以左边要用小括号,也可以:a>>8&0xff; a>>16&0xff; a>>24&0xff;

    这个应用,在安卓中的颜色类Color.java源码中能找到,用4个字节分别存储一个颜色值的:ARGB

  • &1,判断奇偶数

    奇数的末位,总是为1。所以用&1来判断奇偶。 a & 1 == 1 ? "奇数\n": "偶数\n"

按位或(|)


按位或是双目运算符。同位有1得1。

  • 将某一段的8位置为1

    右起,第一段:a|0xff; 第二段:a | 0xff00

  • 两个二的n次幂的整数进行 | 操作

    二的n次幂整数:2, 4, 8, 16…,对应的二进制位:10, 100, 1000, 10000…

    进行 | 操作后,结果就相当于: 两个整数相加的和

按位异或(^)


按位异或是双目运算符。同位相异得1,相同得0。

  • 交换两个变量的值

    int a = 9;
    int b = 10;
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
    printf("交换位置后,a=%d  b=%d \n", a, b);

按位取反(~)


按位取反,是单目运算符。每位1变0,0变1。 ~a;

按位左移(<<)


左移运算:左移多少位,右边就补上多少个0。也就是左移n位,就乘以2的n次冥。

a << 2

按位右移(>>)


右移,是要分符号位的。

在计算机中,不管正数还是负数,都是以补码形式存储的。正数的原码和补码是相同的,符号位为0。负数的补码,等于原码取反,再加1,符号位为1。

正数的右移:右移多少位,左边补多少个0。跟左移类似,即正数右移n位,就除2的n次冥。

负数的右移:保持符号位1不变;右移n位后,再取反码加1

a >> 2

无符号右移(>>>)


(C语言中没有这,Java中有)

正数的无符号右移:和右移是一样的。

负数的无符号右移:右移n位后,左边补n个0,符号位为0

-40 >>> 3;

40的原码:  0 0000 0000 0000 0000 0000 0000 0010 1000
40的反码:  0 1111 1111 1111 1111 1111 1111 1101 0111
-40的补码:     1 1111 1111 1111 1111 1111 1111 1101 1000
右移三位:       1 0001 1111 1111 1111 1111 1111 1111 1011
变符号位为正:    0 0001 1111 1111 1111 1111 1111 1111 1011

猜你喜欢

转载自blog.csdn.net/jjwwmlp456/article/details/78320100