【左程云算法01】二进制和位运算

目录

1. 二进制和位的概念

2. 正数怎么用二进制表达

3. 负数怎么用二进制表达

负数怎么用二进制表达

4.给出一个二进制数怎么判断是十进制的几?(负数时)

5.有符号整数的二进制表示范围

 ​编辑 6.二进制相反数

正数变为负数:

负数变为正数:

例 1:正数变负数(以 3 变 -3 为例)

例 2:负数变正数(以 -3 变 3 为例)

​编辑注意:如果只有4位,-8的相反数没有,没有正数与他对应。也就是负数的最小值是的相反数是没有的​编辑7.位运算

1. 按位与(AND):&

2. 按位或(OR):|

3. 按位异或(XOR):^

4. 按位取反(NOT):~

5. 左移(Shift Left)【后面详细讲】:<<

6. 右移(Shift Right):>>

位运算的优势

左移和右移(非负数版)

8.逻辑运算有三种:

1. 逻辑与(AND):&&

2. 逻辑或(OR):||

综合例子


课程PPT中的详细学习目标:

1. 二进制和位的概念

  • 位(Bit):是计算机中最小的信息单位,只有01两种状态,用来表示一个二进制数位。
  • 二进制:是一种以2为基数的计数法,只有01两个数字,遵循 “满二进一” 的规则。

2. 正数怎么用二进制表达

正数的二进制就是其本身的二进制表示。例如,十进制正数5,用二进制表示为101,计算方法是用除2取余法,将5不断除以2,取余数从下往上排列,即5÷2=212÷2=101÷2=01,所以二进制是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 为例)
  1. 正数 3 的 二进制:0011(最高位 0 表示正)。
  2. 对 3 取反:每一位 0 变 1、1 变 0,得到 1100
  3. 取反后 +1:1100 + 1 = 1101
  4. 结果1101正是 - 3 ,验证成立。
例 2:负数变正数(以 -3 变 3 为例)
  1. 负数 - 3 的 二进制:1101
  2. 对 - 3 的补码取反:1101 → 每一位取反后为 0010
  3. 取反后 +1:0010 + 1 = 0011
  4. 结果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(无符号数默认),可能改变符号。

位运算的优势

  1. 效率极高:直接操作内存,无需经过算术运算的复杂转换。
  2. 节省空间:可通过位运算压缩数据(如用 1 位表示布尔值)。
  3. 算法优化:在加密、哈希、图形处理等领域有不可替代的作用。

左移和右移(非负数版)

左移一位<<拿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);
    }
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值