二进制的探索之旅(Java位运算符:<<、>>、>>>、|、&、^)

二进制的探索之旅


一、二进制的特点

1. 逢一进一

  • 找了张动图,嵌入进来就变静态了,不理解的手动点进去看吧:[看动图]
-5 = 1111 1011
-4 = 1111 1100
-3 = 1111 1101
-2 = 1111 1110
-1 = 1111 1111
0 = 0000 0000
1 = 0000 0001
2 = 0000 0010
3 = 0000 0011
4 = 0000 0100
5 = 0000 0101

2. 负数最高位为1,正数最高位为0

image.png

二、二进制的算法

1. 左位移运算(<<)

左位移:所有位的值向左位移,最左空位(低位)补0

  • 左位移1:同等于该十进制值的两倍
  • 左位移2:同等于该十进制值的四倍
1 = 0000 0001
2 = 0000 0010
4 = 0000 0100
8 = 0000 1000
16 = 0001 0000
32 = 0010 0000
64 = 0100 0000
128 = 1000 0000
  • java实现方式(右位移案例自己脑补)
// 1 = 0000 0001
int num = 1;
// 2 = 0000 0010
System.out.println(num << 1);
// 4 = 0000 0100
System.out.println(num << 2);
// 8 = 0000 1000
System.out.println(num << 3);
// 16 = 0001 0000
System.out.println(num << 4);
// 32 = 0010 0000
System.out.println(num << 5);
// 64 = 0100 0000
System.out.println(num << 6);
// 128 = 1000 0000
System.out.println(num << 7);

2. 右位移运算(>>和>>>)

右位移:所有位的值向右位移,最右空位(高位)补0或补1

  • >> 识别负数,负数高位补1,正数高位补0
/* 结果-2
1111 1101
>>
1111 1110
*/
System.out.println(-3>>1);
/* 结果-1
1111 1110
>>
1111 1111
*/
System.out.println(-2>>1);
/* 结果-1
1111 1111
>>
1111 1111
*/
System.out.println(-1>>1);
/* 结果0
0000 0001
>>
0000 0000
*/
System.out.println(1>>1);
/* 结果1
0000 0010
>>
0000 0001
*/
System.out.println(2>>1);
/* 结果1
0000 0011
>>
0000 0001
*/
System.out.println(3>>1);
/* 结果2
0000 0100
>>
0000 0010
*/
System.out.println(4>>1);
  • >>> 不识别负数,高位始终补0
/* 结果为int最大值-1(2147483646)
... 1111 1101
>>>
0... 1111 1110
*/
System.out.println(-3>>>1);
/* 结果为int最大值(2147483646)
... 1111 1110
>>>
0... 1111 1111
*/
System.out.println(-2>>>1);
/* 结果为int最大值(2147483646)
... 1111 1111
>>>
0... 1111 1111
*/
System.out.println(-1>>>1);

// 正数 >> 和 >>> 都一样
System.out.println(4>>>1);

3. 或运算(|)

  • 把两个值的各个位数做或运算,其中一个位数的值为1则该位数值为1
/* 结果 12
0000 0100
0000 1000
---------
0000 1100
*/
System.out.println(4 | 8);

/* 结果 9
0000 1000
0000 1001
---------
0000 1001
*/
System.out.println(8 | 9);

/* 结果 13
0000 1001
0000 1100
---------
0000 1101
*/
System.out.println(9 | 12);

4. 与运算(&)

  • 把两个值的各个位数做与运算,两个位数的值都为1则该位数值为1
/* 结果 0
0000 0100
0000 1000
---------
0000 0000
*/
System.out.println(4 & 8);

/* 结果 8
0000 1000
0000 1001
---------
0000 1000
*/
System.out.println(8 & 9);

/* 结果 8
0000 1001
0000 1100
---------
0000 1000
*/
System.out.println(9 & 12);

5. 异或运算(^)

  • 把两个值的各个位数做异或运算,两个位数值不相同的该位数值为1
/* 结果 12
0000 0100
0000 1000
---------
0000 1100
*/
System.out.println(4 ^ 8);

/* 结果 1
0000 1000
0000 1001
---------
0000 0001
*/
System.out.println(8 ^ 9);

/* 结果 5
0000 1001
0000 1100
---------
0000 0101
*/
System.out.println(9 ^ 12);

功能小demo

通过二进制运算,只需要一个变量 binaryFlag 实现数字是否重复出现的功能(参考数独算法)

public class Demo {
    static int binaryFlag = 0;

    public static void main(String[] args) {
        System.out.println(exist(1));
        System.out.println(exist(2));
        System.out.println(exist(3));
        // 数字重复,返回 false
        System.out.println(exist(2));
        System.out.println(exist(4));
        System.out.println(exist(5));
    }

    public static boolean exist(int num) {
        int n = (1 << num-1)|binaryFlag;
        boolean res = n != binaryFlag;
        binaryFlag = n;

        return res;
    }
}

总结

  1. 二进制的特性和独有的运算方式可用于特殊的算法逻辑(HashMap: 扩容、hash)
  2. 灵活使用二进制运算可以很好的提高算法效率
  3. >>>>> 都是右位移,区别在于 >> 会识别负数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值