Java位运算,常见的位运算

位运 算 符 中 ,操 作 数 只 能 为 整 型 和字 符 型 数 据 。

按位与(&)

操作数1 0 0 1 1
操作数2 0 1 0 1
按位与 0 0 0 1

按位或(|)

操作数1 0 0 1 1
操作数2 0 1 0 1
按位或 0 1 1 1

按位非(~)

操作数 0 1
按位非 1 0

按位异或(^)

操作数1 0 0 1 1
操作数2 0 1 0 1
按位异或 0 1 1 0

左位移(<<)

溢出截断,低位补0;
在这里插入图片描述

右位移(>>)

溢出截断,高位补符号位;
在这里插入图片描述

无符号右移(>>>)

溢出截断,高位补0;
在这里插入图片描述
在这里插入图片描述

位运算运算法则

1. a^a = 0
2. a^0 = a
3. a^b = b^a
4. a^b^c = (a^b)^c = a^(b^c)
5. a^b^c=0
   a=b^c^d
   b=c^d^a
   c=d^a^b
   d=a^b^c

在这里插入图片描述

常见位运算

1. m*2^n

System.out.println("2^3=" + (1 << 3));// 2^3=8
System.out.println("3*2^3=" + (3 << 3));// 3*2^3=24
System.out.println("5*2^3=" + (5 << 3));// 5*2^3=40

2. 判断一个数n的奇偶性

二进制表示一个数的奇偶性主要看最后一位   为1 则为奇数
								      为0 则为偶数
System.out.println((5 & 1) == 1 ? "奇数" : "偶数"); // 奇数
System.out.println((6 & 1) == 1 ? "奇数" : "偶数"); // 偶数
System.out.println((0 & 1) == 1 ? "奇数" : "偶数"); // 偶数
System.out.println((-1 & 1) == 1 ? "奇数" : "偶数"); // 奇数
System.out.println((-2 & 1) == 1 ? "奇数" : "偶数"); // 偶数

3. 不用临时变量交换两个数

int x = 5;
int y = 6;
x = x ^ y;
y = x ^ y;
x = x ^ y;
System.out.println(x);// 6
System.out.println(y);// 5

4. 取绝对值

System.out.println((-5 ^ (-5 >> 31)) - (-5 >> 31));// 5
System.out.println((0 ^ (0 >> 31)) - (0 >> 31));// 0
System.out.println((5 ^ (5 >> 31)) - (5 >> 31));// 5
System.out.println((6 ^ (6 >> 31)) - (6 >> 31));// 6
System.out.println((7 ^ (7 >> 31)) - (7 >> 31));// 7

4个字节 32位,a>>31取得a的符号;
任何正数右移31后只剩符号位0,溢出的31位截断,空出的31位补符号位0,最终结果为0;
任何负数右移31后只剩符号位1,溢出的31位截断,空出的31位补符号位1,最终结果为 -1;

正数 ^ 0 = 正数本身(二进制不变);
负数 ^ -1 = 它的绝对值 -1(二进制翻转每一位);

以上参考:Java位运算原理及使用讲解

5. 找出没有重复的数

int find(int[] nums){
    
    
    int tmp = nums[0];
    for(int i = 1;i < nums.length; i++)
        tmp ^= arr[i];
    
    return tmp;
}

在这里插入图片描述

总结小经验

  1. 4个字节32位的整数,右移31操作可以取得符号位;
------------------------------------
00000000 01010000 10100000 01011000|
------------------------------------
右移31------------------------------------
                                  0|0000000 01010000 10100000 01011000
------------------------------------
空位补0
------------------------------------
00000000 00000000 00000000 00000000|
------------------------------------
最终结果为 0
------------------------------------
10000000 01010000 10100000 01011000|
------------------------------------
右移31------------------------------------
                                  1|0000000 01010000 10100000 01011000
------------------------------------
空位补0
------------------------------------
11111111 11111111 11111111 11111111|
------------------------------------
最终结果为 -1
  1. 任意二进制 & -1, 会把原二进制里的1找出来;
举例:
   0000 0101 1010
&  1111 1111 1111 
---------------------
   0000 0101 1010
  1. 任意二进制 | 0, 会把原二进制里的0找出来
举例:
   0000 0101 1010
|  0000 0000 0000
---------------------
   0000 0101 1010
  1. 任意二进制 ^ 0, 会保持原二进制;
举例:
   0000 0101 1010
^  0000 0000 0000
---------------------
   0000 0101 1010
  1. 任意二进制 ^ -1, 会把每一位给翻转 (个人理解就是无符号位的取反);
负数  原码 1000	1001	1010	1011	1100	1101	1110	1111
负数绝对值 0000	0001	0010	0011	0100	0101	0110	0111			

反     码 1111	1110	1101	1100	1011	1010	1001	1000

负数反码+负数绝对值
         1111	1111   	1111	1111 	 1111	1111   	1111	1111

1111-1 的补码,在实际开发中就代表了-1;

综上 任意二进制 ^ -1, 会把每一位给翻转;

举例:
   0000 0101 1010
^  1111 1111 1111
---------------------
   1111 1010 0101

在这里插入图片描述
以上参考:几种常见的位运算

C语言位运算的妙用你知道多少?
位运算的妙用
位运算用法

猜你喜欢

转载自blog.csdn.net/weixin_37646636/article/details/120896607