文章目录
1.位运算
针对二进制运算,java提供了位运算符:
运算符 | 说明 |
---|---|
& | 位与 |
^ | 异或 |
~ | 求反 |
<< | 左移位 |
>> | 带符号右移位 |
>>> | 不带符号右移位 |
1.1 位与 &
两个整数值的32位,每一位和每一位求与。
两位都是1与得的结果是1;只要有0结果就是0。
00000000 00000000 00000000 01101001
00000000 00000000 00000000 00100011 &
----------------------------------------
00000000 00000000 00000000 00100001
1.2 位或 |
只要有1结果就是1;两位都是0结果是0。
00000000 00000000 00000000 01101001
00000000 00000000 00000000 00100011 |
----------------------------------------
00000000 00000000 00000000 01101011
1.3 异或 ^
异或运算是“找不同”
不同是1;相同是0。
00000000 00000000 00000000 01101001
00000000 00000000 00000000 00100011 ^
----------------------------------------
00000000 00000000 00000000 01001010
异或还有个特点,就是对同一个值异或两次会得到原值。
试着用上面异或的结果再对第二个值求一次异或,这样可以还原成第一个值。
1.4 求反 ~
1变0;0变1。
求反运算只有一个运算项
00000000 00000000 00000000 01101001 ~
----------------------------------------
11111111 11111111 11111111 10010110
2. 移位运算
2.1 带符号右移位
所有位整体向右移动,右侧移出部分截断。
侧符号位是0,在左侧补0。
符号位是1,在左侧补1。
2.2 不带符号右移位
不管符号位是0还是1,左侧都补0。
1000000000000000000000011101011 >>> 2
结果:
0010000000000000000000000111010
2.3 思考
乘2和除2,除了用 * / 运算符,还可以如何运算?
3.案例练习
3.1 获得任意int
整数的二进制码
代码
package demo2;
import java.util.Scanner;
public class Test1 {
public static void main(String[] args) {
while (true) {
System.out.print("输入整数的二进制码:");
int a = new Scanner(System.in).nextInt();
String code = binaryCode(a);
System.out.println("二进制码: " + code);
}
}
static String binaryCode(int a) {
int p = 1 << 31; //最左侧位是1
String s = "";
for (int i = 0; i < 32; i++) {
int r = a & (p >>> i);
if (r == 0) {
s += "0";
} else {
s += "1";
}
}
return s;
}
}
3.2 int
整数的32位,分拆成4个byte
值
获取左侧第一个字节可以这样做:
- 把左侧第一个字节移动到最右侧
- 强转成 byte,这时会截断 int,只保留右侧末尾的一个字节
以此类推,把每个字节都移动到最右侧再强转成 byte
,就可以完成分拆。
代码
package demo2;
import java.util.Scanner;
public class Test2 {
public static void main(String[] args) {
while (true) {
System.out.print("输入整数:");
int n = new Scanner(System.in).nextInt();
// int 整数转成四个 byte 值
byte[] a = split(n);
for (byte b : a) {
System.out.println(b);
}
}
}
static byte[] split(int n) {
byte[] a = new byte[4];
for (int i = 0; i < a.length; i++) {
// n循环右移四次,分别移动 24,16,8,0 位
a[i] = (byte) (n >> (8 * (3 - i)));
}
return a;
}
}
3.3 四个byte值 合并成一个 int 整数
合并第一个字节
首先准备一个整数0:
我们打算把这个字节放到左侧第一个字节:
byte 运算时会被自动转成 int,变成32位,如果符号位是1,左侧会补1:
我们把这个字节移动到最左侧:
两个值求位或:
合并第二个字节
从上一步的结果开始:
这个个字节会先变成 int,如果符号位是1,左侧会补1:
把它左移到第二个字节位置:
注意看,左侧8位现在都是1
只留下我们需要的8位,把其他24位都抹成0,像下面这样求个位与运算(两位都是1结果是1,有0就是0)
把其他位抹成0了,接下来再求位或,这样就完成了第二个字节的合并:
以此类推,可以继续完成后面两个字节的合并过程。
代码
package demo2;
import java.util.Scanner;
public class Test3 {
public static void main(String[] args) {
while (true) {
byte[] a = new byte[4];
System.out.println("输入四个byte值:");
for (int i = 0; i < a.length; i++) {
a[i] = new Scanner(System.in).nextByte();
}
int r = toInt(a);
System.out.println("合并结果: "+r);
}
}
static int toInt(byte[] a) {
int r = 0;
for (int i = 0; i < a.length; i++) {
// 先向左移动 24,16,8,0 位
int tmp = a[i] << (8 * (3 - i));
// 再把不需要的位抹成0
tmp = tmp & (0b11111111 << (8 * (3 - i)));
// 再求位或
r |= tmp;
}
return r;
}
}