vs不识别0b二进制格式_JAVA中的二进制位基本操作

在平时工作中, 我们很少直接使用二进制和位运算符, 但是涉及到数字或者标识相关的业务,如果能用上二进制,定能为代码增色不少!

使用场景:

1、比如  HashMap 、Disruptor里面取模 代替除法效率更高

d3e73848b06566604a5153969457c7cc.png

2、布隆过滤器的使用也是巧用二进制和hash,以减少内存的使用;

3、标识业务的状态,以减少内存的使用,比如ZooKeeper的ALL权限:

56d219a25266f1895a3758b9e562d397.png

5、开源snowflake雪花算法也是巧用位操作以达到高效生成ID的效果;

4、DP等动态规划的状态压缩很多场景也可以使用二进制进行压缩,以减少内存的使用

... ...

加解密、hash等算法中也是经常使用到,所以掌握二进制算法是迈向高级研发的重要一步,下面来简单介绍一下二进制算法的一些基础知识,希望能达到抛砖引玉的效果;

计算机的二进制操作,主要包括位移(有符号位移、无符号位移)、与、或、异或:

Java中的位操作指定包括:

~                    按位非(NOT)   逐位取反
&                   按位与(AND)   全1为1, 有0为0;  任何数与0异或都等于0。  
|                    按位或(OR)      有1为1, 全0为0。  任何数与0或都等于原值。
^                   按位异或(XOR) 相同为0,相异为1;   任何数与0异或都等于原值。 
>>                 右移                        符号位是0补0,是1补1
>>>               无符号右移           高位补0
<

注意Java中没有无符号左移。

对java一定要注意int(32位)、long(64位)类型,二进制的长度

1. >> 带符号右移。正数右移高位补0,负数右移高位补1。比如:

4 >> 1,结果是2-4 >> 1,结果是-2-2 >> 1,结果是-1

2. >>>:无符号右移。无论是正数还是负数,高位通通补0.

对于正数而言,>>和>>>没区别。对于负数而言,     -2 >>> 1,结果是2147483647(Integer.MAX_VALUE),     -1 >>> 1,结果是2147483647(Integer.MAX_VALUE)

 所以,要判断两个数符号是否相同时,可以这么干:

  return ((a >> 31) ^ (b >> 31)) == 0

3.  & ,位与,一般用于将二进制某些特定位置为1 或0

有了上面的基础知识铺垫,可以尝试做以下涉及二进制位操作的题,以加深理解:

1、给定int  num 的值,不用除法如何判断奇偶性?

int a = 3;System.out.println( (a & 1) == 0 ? "偶数" : "奇数");

2、给定int a、int b 的值,不用加、减、乘、除 、不用额外第三个参数,如何交换a 、 b 的值?

        int a = 10;        int b = 20;        a = a ^ b;        b = a ^ b;        a = a ^ b;

2、给定int num 的值,交换其二进制的 第 i 位 和 第 j 位后的值是多少?

/**     *  交换 x 值的 二进制表示的 第 i 位 和 第j位     *      * @param x     * @param i     * @param j     * @return     */    static int swap_bit(int x, int i, int j) {        // 先判断第i位 和 第 j 位的值是否相等        // 如果相等,则无需交换,直接返回即可        if (((x >> i) & 1) != ((x >> j) & 1)) {            x ^= (1 << i) | (1 << j);        }        return x;    }

3、给定2个 正整数 int a、int b 的值,如何不用加、减、乘、除 计算 a 与 b的乘积?

思路是转换为 二进制 进行计算,应用栈的特性,每次弹出2个计算其和即可,代码如下:

/**   * 利用二进制的加法计算2个int类型和   * @param x   * @param y   * @return   */    public int binaryAdd(int x, int y) {        int v = 0, advance = 0, r = 1;        while (x > 0 || y > 0) {            int i = x & 1;            int j = y & 1;            int b = i ^ j;            if (b > 0) {                // 不相同 一个0 一个 1                if (advance != 0) {                    // 有进位 :1+1 = 0                    b = 0;                }            } else {                // 相同                if ((i & j) > 0) {                    // 都是 1                    if (advance != 0) {                        b = 1;                    } else {                        b = 0;                        // 1+1 = 0,需要进位                        advance = 1;                    }                } else {                    if (advance != 0) {                        b = 1;                        advance = 0;                    } else {                        b = 0;                    }                }            }            if (b > 0) {                b = b << shift(r);                v |= b;            }            r = r << 1;            x = x >> 1;            y = y >> 1;        }        // 计算最后一位还有进位时,再进位        if (advance > 0) {            v |= (advance << shift(r));        }        return v;    }  /**   * 左移动的 位数   * @param r   * @return   */    private int shift(int r) {        int count = 0;        while (r > 0) {            count++;            r = r >> 1;        }        return count - 1;    }  /**   * 乘法   * @param a   * @param b   * @return   */    int binaryMultipy(int a, int b) {        if (a == 0 || b == 0) {            return 0;        }        Stack stack = new Stack<>();        int s = 0;        while (b > 0) {            if ((b & 1) > 0) {                stack.push(a << s);            } else {                stack.push(0);            }            b = b >> 1;            s++;        }        while (stack.size() > 1) {            int x = stack.pop();            int y = stack.pop();            int z = binaryAdd(x, y);            stack.push(z);        }        return stack.pop();    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值