目录
编辑注意:如果只有4位,-8的相反数没有,没有正数与他对应。也就是负数的最小值是的相反数是没有的编辑7.位运算
课程PPT中的详细学习目标:
1. 二进制和位的概念
- 位(Bit):是计算机中最小的信息单位,只有
0
和1
两种状态,用来表示一个二进制数位。 - 二进制:是一种以
2
为基数的计数法,只有0
和1
两个数字,遵循 “满二进一” 的规则。
2. 正数怎么用二进制表达
正数的二进制就是其本身的二进制表示。例如,十进制正数5
,用二进制表示为101
,计算方法是用除2
取余法,将5
不断除以2
,取余数从下往上排列,即5÷2=2
余1
,2÷2=1
余0
,1÷2=0
余1
,所以二进制是101
。
3. 负数怎么用二进制表达
三步走
用正数表达->-1->取反
比如-6如何用二进制表达?
第一步,先写出6的二进制,即0110,
第二步,将第一步得到的-1,即0101,
第三步,将第二步得到的取反,即1010。
给出一个二进制数怎么判断是十进制的几?(负数时)
第一个数字是1确定是负数->取反->+1
比如1000。
第一步,因为首个数字是1,所以是负数
第二步,取反,即0111
第三步,+1,即1000,正数是8
所以1000是-8
可以用以下的类似“坐标轴”的概念来形象理解二进制
负数,即-8~-1区,首个数字都是1,剩余的三位从000到001......到111.
非负数,即0~7区,首个数字是0,剩余的三位从000到到001......到111.
总结有符号数的方法论:
负数怎么用二进制表达
三步走
用正数表达->-1->取反
4.给出一个二进制数怎么判断是十进制的几?(负数时)
第一个数字是1确定是负数->取反->+1(图中的~即为取反的意思)
5.有符号整数的二进制表示范围
当有32位时可以表示多少个数?
1. 左侧区域(负数范围)
- 表示32 位有符号整数中负数的取值范围。为-2的31次方~-1
1. 右侧区域(非负数范围)
- 表示32 位有符号整数中非负数的取值范围。为0~-2的31次方-1
16进制
与二进制联系起来。每四位二进制可以算出一位十六进制。其中需要注意的是,十六进制逢16进1,8还是8,9还是9,到10时因为要用一位表示,显然10有两位,所以借助英文字母来帮忙。
10(即二进制中的1010)在十六进制中为a,
11(即二进制中的1011)在十六进制中为b,
.......
15(即二进制中的1111)在十六进制中为f.
6.二进制相反数
-
正数变为负数:
取反->+1
-
负数变为正数:
取反->+1
例 1:正数变负数(以 3 变 -3 为例)
- 正数 3 的 二进制:
0011
(最高位 0 表示正)。 - 对 3 取反:每一位 0 变 1、1 变 0,得到
1100
。 - 取反后 +1:
1100 + 1 = 1101
。 - 结果
1101
正是 - 3 ,验证成立。
例 2:负数变正数(以 -3 变 3 为例)
- 负数 - 3 的 二进制:
1101
。 - 对 - 3 的补码取反:
1101
→ 每一位取反后为0010
。 - 取反后 +1:
0010 + 1 = 0011
。 - 结果
0011
正是 3 ,验证成立。
注意:如果只有4位,-8的相反数没有,没有正数与他对应。也就是负数的最小值是的相反数是没有的
7.位运算
常见的位运算有以下几种:
1. 按位与(AND):&
- 规则:两个对应位都为 1 时,结果为 1;否则为 0。
- 示例(8 位二进制):
plaintext
1010 1100 & 1100 1010 ----------- 1000 1000
- 用途:
- 提取特定位(如
num & 1
可判断奇偶,结果为 1 则是奇数) - 清零某些位(如
num & 0xffffff00
可清零低 8 位)
- 提取特定位(如
2. 按位或(OR):|
- 规则:两个对应位只要有一个为 1,结果就为 1;否则为 0。
- 示例:
plaintext
1010 1100 | 1100 1010 ----------- 1110 1110
- 用途:
- 设置特定位(如
num | 0x000000ff
可将低 8 位设为 1)
- 设置特定位(如
3. 按位异或(XOR):^
- 规则:两个对应位不同时为 1,相同时为 0(可理解为 “无进位加法”)。
- 示例:
plaintext
1010 1100 ^ 1100 1010 ----------- 0110 0110
- 用途:
- 翻转特定位(如
num ^ 0x000000ff
可翻转低 8 位) - 交换两个数(无需临时变量:
a ^= b; b ^= a; a ^= b;
) - 判断两个数是否相等(
a ^ b == 0
则相等)
- 翻转特定位(如
4. 按位取反(NOT):~
- 规则:将每一位 0 变 1,1 变 0(包括符号位)。
- 示例:
plaintext
~ 1010 1100 ----------- 0101 0011 (8位无符号)
- 注意:在有符号数中,取反结果与原数的关系是
~x = -x - 1
(因补码机制)。- 例如:
~3 = -4
(3 的二进制为000...0011
,取反后为111...1100
,即 - 4 的补码)。
- 例如:
5. 左移(Shift Left)【后面详细讲】:<<
- 规则:将二进制位整体向左移动 n 位,右侧补 0。
- 示例:
1010 << 2
→101000
(相当于乘以 2ⁿ)。 - 注意:左移可能改变符号位(正数可能变负数)。
6. 右移(Shift Right):>>
- 规则:
- 算术右移(多数语言默认):整体右移 n 位,左侧补与原符号位相同的值(保持符号不变)。
- 示例:
-8 >> 2
(补码11111000
)→11111110
(即 - 2,相当于除以 2ⁿ并向下取整)。
- 示例:
- 逻辑右移:左侧补 0(无符号数默认),可能改变符号。
- 算术右移(多数语言默认):整体右移 n 位,左侧补与原符号位相同的值(保持符号不变)。
位运算的优势
- 效率极高:直接操作内存,无需经过算术运算的复杂转换。
- 节省空间:可通过位运算压缩数据(如用 1 位表示布尔值)。
- 算法优化:在加密、哈希、图形处理等领域有不可替代的作用。
左移和右移(非负数版)
左移一位<<拿0补
右移>>拿0补
负数时,>>拿符号位补,>>>拿0补
public class BinarySystem {
// 输出整数的二进制表示(32位)
public static void printBinary(int num) {
for (int i = 31; i >= 0; i--) {
System.out.print((num >>> i) & 1);
}
System.out.println();
}
public static void main(String[] args) {
// 测试非负数的左移
int i = 0b00011010;
System.out.println("===i << ===");
printBinary(i);
printBinary(i << 1);
printBinary(i << 2);
printBinary(i << 3);
// 测试非负数的右移和无符号右移(效果一样)
System.out.println("===i >> >>>===");
printBinary(i);
printBinary(i >> 2);
printBinary(i >>> 2);
// 测试负数的右移和无符号右移(效果不一样)
int j = 0b11110000000000000000000000000000;
System.out.println("===j >> >>>===");
printBinary(j);
printBinary(j >> 2);
printBinary(j >>> 2);
// 测试左移与乘以2的关系
System.out.println("非负数左移与乘以2的关系:");
int num = 5;
System.out.println(num + " << 1 = " + (num << 1) + ",等同于 " + (num * 2));
System.out.println(num + " << 2 = " + (num << 2) + ",等同于 " + (num * 4));
// 测试右移与除以2的关系
System.out.println("非负数右移与除以2的关系:");
num = 80;
System.out.println(num + " >> 1 = " + (num >> 1) + ",等同于 " + (num / 2));
System.out.println(num + " >> 2 = " + (num >> 2) + ",等同于 " + (num / 4));
}
}
注意:位运算与逻辑运算区分开。
8.逻辑运算有三种:
1. 逻辑与(AND):&&
- 规则:两个条件都为真时,结果才为真;否则为假。
true && true = true
true && false = false
false && true = false
false && false = false
- 短路特性:如果第一个条件为假,直接返回假,不再判断第二个条件(提高效率)。
- 示例:
java
运行
int a = 5, b = 10; boolean result = (a > 0) && (b < 20); // true(两个条件都满足) boolean shortCircuit = (a < 0) && (b++ > 0); // false,且b不会自增(短路)
2. 逻辑或(OR):||
- 规则:两个条件至少有一个为真时,结果为真;都为假时才为假。
true || true = true
true || false = true
false || true = true
false || false = false
- 短路特性:如果第一个条件为真,直接返回真,不再判断第二个条件。
- 示例:
java
运行
int a = 5, b = 10; boolean result = (a > 10) || (b < 20); // true(第二个条件满足) boolean shortCircuit = (a > 0) || (b++ > 0); // true,且b不会自增(短路)
综合例子
public class BitwiseOperationsDemo {
/**
* 打印整数的32位二进制表示
* @param num 要打印的整数
*/
public static void printBinary(int num) {
// 从最高位(第31位)到最低位(第0位)依次处理
for (int i = 31; i >= 0; i--) {
// 无符号右移i位,再与1进行按位与,获取当前位的值
// >>> 是无符号右移,高位补0,确保符号位也能正确显示
System.out.print((num >>> i) & 1);
// 每4位加一个空格,增强可读性
if (i % 4 == 0) {
System.out.print(" ");
}
}
System.out.println(); // 换行
}
public static void main(String[] args) {
// 1. 按位与(&)操作演示
System.out.println("=== 按位与(&)操作 ===");
int a = 0b10101100; // 二进制表示:10101100(十进制172)
int b = 0b11001010; // 二进制表示:11001010(十进制202)
int andResult = a & b; // 按位与结果
System.out.print("a: "); printBinary(a);
System.out.print("b: "); printBinary(b);
System.out.print("a & b: "); printBinary(andResult);
System.out.println("用途示例:判断奇偶数 - " + (a & 1) + "(1为奇数,0为偶数)\n");
// 2. 按位或(|)操作演示
System.out.println("=== 按位或(|)操作 ===");
int orResult = a | b; // 按位或结果
System.out.print("a: "); printBinary(a);
System.out.print("b: "); printBinary(b);
System.out.print("a | b: "); printBinary(orResult);
System.out.println("用途示例:设置特定位 - 低8位设为1: " + (a | 0xFF) + "\n");
// 3. 按位异或(^)操作演示
System.out.println("=== 按位异或(^)操作 ===");
int xorResult = a ^ b; // 按位异或结果
System.out.print("a: "); printBinary(a);
System.out.print("b: "); printBinary(b);
System.out.print("a ^ b: "); printBinary(xorResult);
System.out.println("用途示例:翻转特定位 - 低4位翻转: ");
System.out.print("原始值: "); printBinary(a);
System.out.print("翻转后: "); printBinary(a ^ 0x0F);
System.out.println();
// 4. 按位取反(~)操作演示
System.out.println("=== 按位取反(~)操作 ===");
int notResult = ~a; // 按位取反结果
System.out.print("a: "); printBinary(a);
System.out.print("~a: "); printBinary(notResult);
System.out.println("公式验证:~a = -a - 1 → " + notResult + " = " + (-a - 1) + "\n");
// 5. 左移(<<)操作演示
System.out.println("=== 左移(<<)操作 ===");
int leftShift1 = a << 1; // 左移1位
int leftShift2 = a << 2; // 左移2位
System.out.print("a: "); printBinary(a);
System.out.print("a << 1: "); printBinary(leftShift1);
System.out.print("a << 2: "); printBinary(leftShift2);
System.out.println("数值关系:a = " + a + ", a << 1 = " + leftShift1 + " = " + (a * 2));
System.out.println("数值关系:a << 2 = " + leftShift2 + " = " + (a * 4) + "\n");
// 6. 右移操作演示(算术右移与无符号右移)
System.out.println("=== 右移操作 ===");
int negativeNum = -172; // 负数示例
System.out.println("负数原始值: " + negativeNum);
System.out.print("二进制: "); printBinary(negativeNum);
// 算术右移(>>):高位补符号位(保持符号不变)
int rightShift = negativeNum >> 2;
// 无符号右移(>>>):高位补0(可能改变符号)
int unsignedRightShift = negativeNum >>> 2;
System.out.print("算术右移2位 (>>): "); printBinary(rightShift);
System.out.println("数值: " + rightShift);
System.out.print("无符号右移2位 (>>>): "); printBinary(unsignedRightShift);
System.out.println("数值: " + unsignedRightShift + "\n");
// 7. 实际应用:判断一个数是否为2的幂
System.out.println("=== 实际应用示例 ===");
int powerOfTwo = 16; // 2的4次方
int notPowerOfTwo = 18;
// 2的幂的二进制只有一个1,减1后全为1,与运算结果为0
boolean isPower1 = (powerOfTwo & (powerOfTwo - 1)) == 0;
boolean isPower2 = (notPowerOfTwo & (notPowerOfTwo - 1)) == 0;
System.out.println(powerOfTwo + " 是2的幂: " + isPower1);
System.out.println(notPowerOfTwo + " 是2的幂: " + isPower2);
// 8. 实际应用:不使用临时变量交换两个数
int x = 10, y = 20;
System.out.println("\n交换前: x=" + x + ", y=" + y);
x ^= y; // x = x ^ y
y ^= x; // y = y ^ (x ^ y) = x
x ^= y; // x = (x ^ y) ^ x = y
System.out.println("交换后: x=" + x + ", y=" + y);
}
}