JAVA基础提高之位运算
注:JAVA位运算在阅读JDK源码时候常常会遇到,因此学习位运算相关知识,是非常有必要的,在学习之前,首先需要了解一下二进制码相关知识,这里给大家提供几篇相关文章:《源码,补码,反码》
首先,大家都知道,JAVA定义的位运算符可以应用于整数类型(int),长整型(long),短整型(short),字符型(char),和字节类型(byte)等类型。
Java七种位运算符:
位运算符 | 说明 |
---|---|
>> | 右移运算符,符号左侧数值 按位右移 符号右侧数值指定的位数,若为正数则高位补0,若为负数则高位补1 |
<< | 左移运算符,符号左侧数值 按位左移 符号右侧数值指定的位数,并在低位处补0 |
>>> | 无符号右移运算符,符号左侧数值 按位右移 符号右侧数值指定的位数,无论正负高位补0 |
& | 与(AND)运算符,对两个整型操作数中对应位执行布尔代数,两个位都为1时输出1,否则0 |
| | 或(OR)运算符,对两个整型操作数中对应位执行布尔代数,两个位中只要有一个为1就输出1,否则为0 |
^ | 异或(XOR)运算符,对两个整型操作数中对应位执行布尔代数,两个位相等则为0,不相等则为1 |
~ | 非(NOT)运算符,按位取反运算符翻转操作数的每一位,即0变成1,1变成0 |
七种位运算符使用实例代码:
/**
* @Auther: csp1999
* @Date: 2020/10/26/11:33
* @Description: 位运算操作符
*/
public class bit_operators { @Test public void test01() { // int max = Integer.MAX_VALUE; // int min = Integer.MIN_VALUE; int num1 = -20; int num2 = 30; int bit_operator_1 = num1 << 1;// 正数左移n位扩大2^(n)倍,负数左移n位缩小2^(n)倍 int bit_operator_2 = num1 >> 1;// 正数右移n位缩小2^(n)倍,负数右移n位扩大2^(n)倍 int bit_operator_3 = num1 >>> 1;// 无符号右移 切记要明白计算机存储二进制都是以补码的形式存储 int bit_operator_4 = num1 & num2; int bit_operator_5 = num1 | num2; int bit_operator_6 = num1 ^ num2; int bit_operator_7 = ~num1; // System.out.println(max); // System.out.println(min); // System.out.println("0"+Integer.toBinaryString(Integer.MAX_VALUE)); // System.out.println(Integer.toBinaryString(20)); System.out.println(bit_operator_1); System.out.println(bit_operator_2); System.out.println(bit_operator_3); System.out.println(bit_operator_4); System.out.println(bit_operator_5); System.out.println(bit_operator_6); System.out.println(bit_operator_7); }
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
运算结果如下:
-4
-1
2147483647
2
-2
-4
1
- 1
- 2
- 3
- 4
- 5
- 6
- 7
原理解析(高位0为手动补齐,方便观看)
a = 11111111 11111111 11111111 11101100
b = 00000000 00000000 00000000 00011110
------------------------------------------------
a << 1 --> 11111111 11111111 11111111 11011000
a >> 1 --> 11111111 11111111 11111111 11110110
a >>> 1 --> 01111111 11111111 11111111 11110110
a & b = 00000000 00000000 00000000 00001100
a | b = 11111111 11111111 11111111 11111110
a ^ b = 11111111 11111111 11111111 11110010
~a = 00000000 00000000 00000000 00010011
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
进行位操作时,除long型外,其他类型会自动转成int型,转换之后,可接受右操作数长度为32。进行位运算时,总是先将短整型和字节型值转换成整型值再进行移位操作的。
数据类型 | 大小 |
---|---|
byte | 8 bit |
short | 16 bit |
char | 16 bit |
int | 32 bit |
long | 64bit |
示例:
byte num1 = -128;
byte num2 = 63;
byte bit_operator_1 = (byte)(a << 1);
byte bit_operator_2 = (byte)(a >> 1);
byte bit_operator_3 = (byte)(a >>> 1);
byte bit_operator_4 = (byte)(a & b);
byte bit_operator_5 = (byte)(a | b);
byte bit_operator_6 = (byte)(a ^ b);
byte bit_operator_7 = (byte)(~ a);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
上面的代码在位运算后类型自动提升为了int,所以需要使用int类型的变量来接受,但是我们可以在进行位运算后进行强转,但强转会直接截取字节,从而导致丢失精度,最终得到的结果如下:
0
-64
-64
0
-65
-65
127
- 1
- 2
- 3
- 4
- 5
- 6
- 7
对于 int 类型的整数移位 num1 >> num2, 当 b>32 时,系统先用 num2 对 32 求余(因为 int 是 32 位),得到的结果才是真正移位的位数,例如,num1 >> 33 和 num1 >> 1 的结果相同,而 num1>> 32 = num1;
位运算的使用场景如下:
1.判断奇偶
@Test
public void test02() { Integer num = 123; // 判断奇偶普通方式一: if (num % 2 == 0) { System.out.println("偶数"); } else { System.out.println("奇数"); } // 判断奇偶位运算方式二: if ((num & 1) == 0) { System.out.println("偶数"); } else if ((num & 1) == 1) { System.out.println("奇数"); }
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
偶数的最低位肯定是0,奇数的最低位肯定是1,而1的最低位是1其他位都为零,当进行与运算时:
- 偶数必然:a&1 == 0
- 奇数必然:a&1 == 1
2. 不使用中间变量交换两个数
@Test
public void test03() { int a = 10; int b = 20; // 1.依靠中间变量交换2个数值: int c; c = a; a = b; b = c; System.out.println("a=" + a + ",b=" + b); // 2. 位运算不使用中间变量交换2个数: a = 10; b = 20; a = a ^ b; b = b ^ a; a = a ^ b; System.out.println("a=" + a + ",b=" + b);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
这里需要知道两点:
- 任何数和自己进行异或操作结果都为0
- 异或符合交换律,即a ^ b = b ^ a
好的,那么上面代码操作就等于:
a = a ^ b;
b = b ^ a = b ^ (a ^ b) = a;
a = a ^ b = (a ^ b) ^ (b ^ (a ^ b)) = (a ^ b) ^ a = b;
- 1
- 2
- 3
3. 判断一个正整数是不是2的整数次幂
public boolean power(int num) { if (num <= 0) { System.out.println("这里不计算负数,直接返回false"); return false; } else { return (num & (num - 1)) == 0; }
}
@Test
public void test04() { int num = 1024; System.out.println(power(num));
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
任何正整数如果是2的幂数,都形如下:
10
100
1000
10...0
1234
- 1
- 2
- 3
- 4
- 5
即首位都为1,往后位数都为0,那么在减去1后又都形如下:
01
011
0111
01...1
1234
- 1
- 2
- 3
- 4
- 5
所以大于零的2的幂数和自己减一后的数进行与运算结果必然为0
4. 对称加密
就是使用一次异或加密,使用两次异或解密:
@Test
public void test5(){ String a = "sadfsdfsdfhfghf123dfgfg"; System.out.println(a); int key = 324545231; byte[] bytes = a.getBytes(); for (int i = 0; i < bytes.length-1; i++) { bytes[i] = (byte)(bytes[i] ^ key); } String b = new String(bytes); System.out.println(b); for (int i = 0; i < bytes.length-1; i++) { bytes[i] = (byte)(bytes[i] ^ key); } String c = new String(bytes); System.out.println(c);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
打印结果:
sadfsdfsdfhfghf123dfgfg
����������������������g
sadfsdfsdfhfghf123dfgfg
- 1
- 2
- 3
以上是JAVA位运算的基本实例和知识点,同样位运算也广泛应用于JDK源码中,对于初次学习JDK源码的小伙伴,位运算基本知识是需要的。最后给大家推荐一个宝藏博主:[枣面包]
文章来源: csp1999.blog.csdn.net,作者:兴趣使然の草帽路飞,版权归原作者所有,如需转载,请联系作者。
原文链接:csp1999.blog.csdn.net/article/details/109286491
- 点赞
- 收藏
- 关注作者
评论(0)