search.png
关于我
menu.png
Java review(9) 位运算

很少人会用Java写位运算吧,也许有的人想到这么底层的东西会觉得可能只有c支持,但是Java的位运算和c基本是类似的。

    @Test
    public void test1() throws Exception {
        Byte b1 = Byte.parseByte("-1110101", 2);
        System.out.println("b1: " + b1 + " " + Integer.toBinaryString(b1));

        Byte b2 = Byte.parseByte("1110101", 2);
        System.out.println("b2: " + b2 + " " + Integer.toBinaryString(b2));

        int b3 = b1 | b2;
        System.out.println("b1 | b2: " + b3 + " " + Integer.toBinaryString(b3));
        b3 = b1 & b2;
        System.out.println("b1 & b2: " + b3 + " " + Integer.toBinaryString(b3));
        b3 = b1 ^ b2;
        System.out.println("b1 ^ b2: " + b3 + " " + Integer.toBinaryString(b3));
        b3 = ~b1;
        System.out.println("~ b1: " + b3 + " " + Integer.toBinaryString(b3));
        b3 = b1 >> 2;
        System.out.println("b1 >> 2: " + b3 + " " + Integer.toBinaryString(b3));
        b3 = b1 << 2;
        System.out.println("b1 << 2: " + b3 + " " + Integer.toBinaryString(b3));
        b3 = b1 >>> 2;
        System.out.println("b1 >>> 2: " + b3 + " " + Integer.toBinaryString(b3));
    }

输出,为了方便查看,进行了对齐,Integer.toBinaryString在输出时会忽略之前的0,在看的时候可以把空白的地方想象成都是0:

b1:         -117         11111111111111111111111110001011
b2:         117                                  1110101
b1 | b2:     -1             11111111111111111111111111111111
b1 & b2:     1                                            1
b1 ^ b2:     -2             11111111111111111111111111111110
~ b1:         116                                  1110100
b1 >> 2:     -30         11111111111111111111111111100010
b1 << 2:     -468         11111111111111111111111000101100
b1 >>> 2:     1073741794       111111111111111111111111100010

与或非异或运算都很直白。

这里讲一下>>、<<和>>>的区别:

  • >> 在移位的时候保留符号
  • << 左移位,在最右边进行补0
  • >>> 在移位的时候不保留符合,而往左边补0

因此>>>也称作无符号移位。此外只有>>>而没有<<<

看测试例子:

    @Test
    public void test2() throws Exception {
        Byte b = Byte.parseByte("10101", 2);
        System.out.println("b: " + Integer.toBinaryString(b) + " b >> 2: " + Integer.toBinaryString(b >> 2));
        System.out.println("b: " + Integer.toBinaryString(b) + " b >>> 2: " + Integer.toBinaryString(b >>> 2));
        b = Byte.parseByte("-10101", 2);
        System.out.println("b: " + Integer.toBinaryString(b) + " b >> 2: " + Integer.toBinaryString(b >> 2));
        System.out.println("b: " + Integer.toBinaryString(b) + " b >>> 2: " + Integer.toBinaryString(b >>> 2));

    }

结果:

b: 10101 b >> 2: 101
b: 10101 b >>> 2: 101
b: 11111111111111111111111111101011 b >> 2: 11111111111111111111111111111010
b: 11111111111111111111111111101011 b >>> 2: 111111111111111111111111111010

以下对移位和乘除法的性能进行了验证:

  1. 验证正确性:
    ```java
    @Test
    public void test3() throws Exception {
    byte b = 66;

    long start = System.currentTimeMillis();
    for (int i = 0; i < 1; i ++) {
    b >>= 3;
    System.out.println(b);
    b <<= 3;
    System.out.println(b);
    }
    long end = System.currentTimeMillis();
    System.out.println("使用移位:" + (end-start) + "ms");


    start = System.currentTimeMillis();
    for (int i = 0; i < 1; i ++) {
    b /= 8;
    System.out.println(b);
    b *= 8;
    System.out.println(b);
    }
    end = System.currentTimeMillis();
    System.out.println("使用乘法:" + (end-start) + "ms");
    }
可以看到二者输出是一致的

```java
8
64
使用移位:0ms
8
64
使用乘法:0ms
  1. 性能验证,因为编译器进行了优化,移位运算的性能并没有比直接乘除快:
 @Test
    public void test3() throws Exception {
        byte b = 66;

        long start = System.currentTimeMillis();
        for (int i = 0; i < 500000; i ++) {
            b >>= 3;
            // System.out.println(b);
            b <<= 3;
            // System.out.println(b);
        }
        long end = System.currentTimeMillis();
        System.out.println("使用移位:" + (end-start) + "ms");


        start = System.currentTimeMillis();
        for (int i = 0; i < 500000; i ++) {
            b /= 8;
            // System.out.println(b);
            b *= 8;
            // System.out.println(b);
        }
        end = System.currentTimeMillis();
        System.out.println("使用乘除法:" + (end-start) + "ms");
    }

结果:

使用移位:11ms
使用乘除法:8ms

版权声明

知识共享许可协议 本文章由作者“衡于墨”创作,转载请注明出处,未经允许禁止用于商业用途

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。
发布时间:2019年11月28日 16:28:42

评论区#

还没有评论哦,期待您的评论!

关闭特效