美文网首页数据结构
Java 负数二进制转换、位移、位运算

Java 负数二进制转换、位移、位运算

作者: xujicheng | 来源:发表于2019-08-22 00:58 被阅读0次

    Java 中 int型->32bit
    范围-2147483648~2147483647
    [1000,0000,0000,0000,0000,0000,0000,0000~0111,1111,1111,1111,1111,1111,1111,1111]
    其中左起最高位是符号位 1表示负数 0表示正数

    1. 正负数如何转换呢

    例如:5 [0000,0000,0000,0000,0000,0000,0000,0101]

    • 对原码二进制进行取反操作
      1111,1111,1111,1111,1111,1111,1111,1010
    • 对取反后的结果进行补码[+1]操作得到-5的二进制
      1111,1111,1111,1111,1111,1111,1111,1011
    1. 左位移 <<
      例如:

       //5 [0000,0000,0000,0000,0000,0000,0000,0101] 
       int i = 5 << 1;
       //[0000,0000,0000,0000,0000,0000,0000,1010]  = 10
       int I = 5 << 2;
       // [0000,0000,0000,0000,0000,0000,0001,0100]  = 20
      
       //6 [0000,0000,0000,0000,0000,0000,0000,0110] 
       int i = 6 << 1;
       //  [0000,0000,0000,0000,0000,0000,0000,1100] =12
       int I = 6 << 2;
       //  [0000,0000,0000,0000,0000,0000,0001,1000] =24
      

    二进制左移一位,其实就是将数字翻倍

    1. 右位移 >>
      例如 :
    //5 [0000,0000,0000,0000,0000,0000,0000,0101] 
      int i = 5 >> 1;
      //[0000,0000,0000,0000,0000,0000,0000,0010]  = 2
      int I = 5 >> 2;
      // [0000,0000,0000,0000,0000,0000,0000,0000]  = 1
    
      //6 [0000,0000,0000,0000,0000,0000,0000,0110] 
      int i = 6 >> 1;
      //  [0000,0000,0000,0000,0000,0000,0000,0011] =3
      int I = 6 << 2;
      //  [0000,0000,0000,0000,0000,0000,0000,0001] =1
    

    二进制右移一位,就是将数字除以 2 并求整数

    1. 右位移 >> 和 >>>的区别

    Java中定义了2种右移:逻辑右移>>>和算术右移>>
    目的是为了符号位是1是否右移。
    逻辑右移>>>一位 左边补0
    算术右移>>一位 左边补1
    验证一下:

            System.out.println(Integer.toBinaryString(Integer.MIN_VALUE));
            System.out.println(Integer.MIN_VALUE);
            System.out.println(Integer.toBinaryString(Integer.MIN_VALUE>>>1));
            System.out.println(Integer.MIN_VALUE>>>1);
            System.out.println(Integer.toBinaryString(Integer.MIN_VALUE>>1));
            System.out.println(Integer.MIN_VALUE>>1);
    
            /**
             * 10000000000000000000000000000000
             * -2147483648
             * 1000000000000000000000000000000
             * 1073741824
             * 11000000000000000000000000000000
             * -1073741824
             */
            System.out.println("----------------------------------------------");
            System.out.println(Integer.toBinaryString(Integer.MAX_VALUE));
            System.out.println(Integer.MAX_VALUE);
            System.out.println(Integer.toBinaryString(Integer.MAX_VALUE>>>1));
            System.out.println(Integer.MAX_VALUE>>>1);
            System.out.println(Integer.toBinaryString(Integer.MAX_VALUE>>1));
            System.out.println(Integer.MAX_VALUE>>1);
    
            /**
             * 01111111111111111111111111111111
             * 2147483647
             * 00111111111111111111111111111111
             * 1073741823
             * 00111111111111111111111111111111
             * 1073741823
             */
    

    目前看 逻辑右移和算术右移只是对负数有区别,算术右移是带着符号位右移并补上原先的符号位。
    那么左移是否会影响到符号位呢?
    验证一下

            System.out.println(Integer.toBinaryString(Integer.MAX_VALUE));
            System.out.println(Integer.MAX_VALUE);
            System.out.println(Integer.toBinaryString(Integer.MAX_VALUE<<1));
            System.out.println(Integer.MAX_VALUE<<1);
            /**
             * 01111111111111111111111111111111
             * 2147483647
             * 11111111111111111111111111111110
             * -2
             */
    

    可见左移永远只在末尾补0,会影响符号位。

    1. 位运算 & 、|、^

    bit 0、1 分别代表了假、真

    • | :逻辑或 参与操作的位中只要有一个位是 1,那么最终结果就是 1

    例如
    2147483647 | -2 = -1

        01111111111111111111111111111111
        11111111111111111111111111111110
      ----逻辑或(|)------------------------
       =11111111111111111111111111111111
    
    ```
        System.out.println(Integer.toBinaryString(2147483647|-2));
        System.out.println(2147483647|-2);
        // -1 逻辑或任何数的结果都是-1
        System.out.println(Integer.toBinaryString(-1|4325));
        System.out.println(-1|4325);
        /**
         *11111111111111111111111111111111
         * -1
         * 11111111111111111111111111111111
         * -1
         */
    ```
    
    • &:逻辑与 参与操作的位中必须全都是 1,那么最终结果才是 1

      例如
      2147483647 & -2 = 2147483646

        01111111111111111111111111111111
        11111111111111111111111111111110
      ----逻辑与(&)------------------------
       =01111111111111111111111111111110
    
    ```
        System.out.println(Integer.toBinaryString(2147483647&-2));
        System.out.println(2147483647&-2);
        /**
         * 01111111111111111111111111111110
         * 2147483646
         */
    ```
    
    • ^:逻辑异或 参与操作的位相同,那么最终结果就为 0,否则为 1

    例如
    2147483647 ^ -2 = 2147483646

        01111111111111111111111111111111
        11111111111111111111111111111110
      ----逻辑异或(^)------------------------
       =10000000000000000000000000000001
    
    ```
        System.out.println(Integer.toBinaryString(2147483647^-2));
        System.out.println(2147483647^-2);
        //所有的数异或自身都为0
        System.out.println(2345^2345);
        System.out.println(-2^-2);
        /**
         * 10000000000000000000000000000001
         * -2147483647
         * 0
         * 0
         */
    ```
    

    相关文章

      网友评论

        本文标题:Java 负数二进制转换、位移、位运算

        本文链接:https://www.haomeiwen.com/subject/emgwsctx.html