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. 对于 >><< 的运算

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