Skip to content

位运算


原码,反码,补码 ​

(1) 二进制的最高位是符号位:0 表示正数,1 表示负数(怎么记? 1旋转一下变成-) ​

(2) 正数 ​

正数的原码、反码、补码都一样(三码合一) ​

(3) 负数 ​

负数的反码:原码的符号位不变,其他位取反(0 - > 1 , 1 - > 0) ​

负数的补码 = 负数的反码 + 1 ​

负数的反码 = 负数的补码 - 1 ​

(4) 0 的反码、补码都是 0 ​

(5) java 没有无符号数,换言之,java 中的数字都是有符号的 ​

两个核心 ​

(1) 计算机运算时,都是以补码的方式来运算的 ​

(2) 当我们看运算结果的时候,要看它的原码 ​


⭐ 位运算 ​

1. 位运算符 ​

(1)按位与& ​

(2)按位或| ​

(3)按位异或^ ​

(4)按位取反~ ​

2. 运算规则 ​

提示:先将左右操作数转换成二进制,计算过程是采用补码计算 ​

(1)按位&:两位全为 1,结果为 1,否则为 0 ​

(2)按位或|:两位有一个为 1,结果为 1,否则为 0 ​

(3)按位取反~:0 - > 1 , 1 - > 0 ​

(4)按位异或^:两位一个为 0,一个为 1,结果为 1,否则为 0 ​

小结:不相同结果为 1,相同结果为 0 ​

3. 算术位移 ​

(1)算术左移 <<:符号位不变,低位溢出(整体右移),移动位数等于位移位数,高位空出的位置由符号位补齐 ​

无论正数、负数,低位都是补 0 ​

举例 ​

int c = 1 << 2; // 1 --> 00000001 --> 00000100(红色的就是溢出位,位移位数为 2,溢出两位) ​

本质:1 * 2 *2 = 4 ​

速算结果:表示乘以 2 的次数(位移位数),上述例子中,想左位移两位,乘两次 2 ​

(2)算术右移 >>(有符号右移):符号位不变,低位溢出(整体右移),移动位数等于位移位数,高位空出的位置由符号位补齐 ​

正数:高位补 0 ​

负数:高位补 1 ​

举例 ​

int a = 1 >> 2 : // 1 --> 00000001 --> 00000000 (红色的就是溢出位,位移位数为 2,溢出两位) ​

本质 :1 / 2 / 2 = 0 ​

速算方法:表示除以 2 的次数(位移位数),上述例子中,向右位移两位,除两次 2 ​

(3) 无符号右移>>>:符号位不变,低位溢出(整体右移),移动位数等于位移位数,高位空出的位置由符号位补齐 ​

无论正数、负数,高位都是补 0 ​

特别说明:没有 <<< 符号 ​


代码示例 ​

温馨提示:int 数据类型为 4 个字节大小 ​

java
// 位运算
public class BitOperator {

    // 编写一个main方法
    public static void main(String[] args) {

        // 推导过程
        // 1. 先得到 2的补码 => 2的原码 00000000 00000000 00000000 00000010
        //    2的补码 00000000 00000000 00000000 00000010
        // 2. 3的补码 3的原码 00000000 00000000 00000000 00000011
        //    3的补码 00000000 00000000 00000000 00000011
        // 3. 按位&
        //    00000000 00000000 00000000 00000010
        //    00000000 00000000 00000000 00000011
        //    00000000 00000000 00000000 00000010 & 运算后的补码
        //    运算后的原码 也是 00000000 00000000 00000000 00000010
        //    结果就是 2
        System.out.println(2 & 3); // 2

        // 推导
        // 1. 先得到 -2的原码 10000000 00000000 00000000 00000010
        // 2. -2的 反码 11111111 11111111 11111111 11111101
        // 3. -2的 补码 11111111 11111111 11111111 11111110
        // 4. ~-2操作 00000000 00000000 00000000 00000001 运算后的补码
        // 5. 运算后的原码 就是 00000000 00000000 00000000 00000001 => 1
        System.out.println(~-2); // 1

        // 推导
        // 1. 得到2的补码 00000000 00000000 00000000 00000010
        // 2. ~2操作 11111111 11111111 11111111 11111101 运算后的补码
        // 3. 运算后的反码 11111111 11111111 11111111 11111100
        // 4. 运算后的原码 10000000 00000000 00000000 00000011 => -3
        System.out.println(~2); // -3

        System.out.println(1 >> 2); // 0
        System.out.println(1 << 2); // 4
        System.out.println(4 << 3); // 4 * 2 * 2 * 2 = 32
        System.out.println(15 >> 2); // 15 / 2 / 2 = 3

        System.out.println(-10.4 % 3); // -1.4 近似值

        int i = 66;
        System.out.println(++i + i); // 134
    }
}

小结 ​

1. 对于 &、 |、 ^、 ~ 的运算 ​

(1)计算机运算时,都是以补码的方式来运算的,首先得到操作数的补码 ​

(2)看是什么运算符,回想对应的操作规则,操作补码 ​

(3)补码 ---> 原码,得到计算结果 ​

2. 对于 >>、<< 的运算 ​

按照速算方法计算结果即可 ​