美文网首页
java位运算常用操作

java位运算常用操作

作者: 小小的coder | 来源:发表于2020-01-16 13:46 被阅读0次
    java中常用的7个位运算符:

    & 同为1则为1 否则为0
    | 一位为1 则返回1
    ~ 将操作数的每位取反
    ^ 两位相同时返回0,不同时返回1
    << 左移运算符 将操作数的二进制码整体左移指定位数,右边空出的以0填充 正数---乘2^n
    >> 右移运算符 将操作数的二进制码整体右移指定位数,左边空出的以符号位填充(如果是正数,就是以0填充。如果是负数,就是以1填充。) 正数---除2^n
    >>>无符号右移运算符 将操作数的二进制码整体右移指定位数,左边空出来的位总是以0填充。 正数---除2^n

    说明:位运算的效率高于乘除运算,因为计算机底层就是0 1二进制来处理的。

    位运算优先级

    ~的优先级最高,其次是<<、>>和>>>,再次是&,然后是^,优先级最低的是|。

    位运算总的来说比较简单,但是应用却是很多,要能熟练掌握并使用常用的应用。

    位运算基础操作

    //对于任意整数 a 和 b,以下表达式的结果均成立

    a|0 == a;
    a&-1 == a;
    a&0 == 0;
    
    a^a == 0;
    a^0 == a;
    
    a|~a == -1;
    a&~a == 0;
    a&a == a;
    a|a == a;
    
    a|(a&b) == a;
    a&(a|b) == a;
    
    应用一:判断奇偶数
    a&1 == 0;则a为偶数
    a&1 == 1;则a为奇数
    

    说明: 1的二进制表示形式除了最后一位其余所有的位都是0,所以a&1对应的除了最后一位全部是0,我们知道,一个数如果是偶数,则最后一位二进制位肯定是0,因为其他位都是2的整数次方,而如果一个数是奇数,则最后一位二进制位肯定是1。所以,当a&1 == 0时,说明a是偶数,当a&1 == 1时,说明a是奇数。

    应用二:交换两数
    int a = 5;
    int b = 9;
    a ^= b;
    b ^= a;
    a ^= b;
    

    说明:直接看第二步,其实就是这样:b = b^ (a^b) = a;

    因为异或运算满足交换律,一个数亦或自己结果为0,而任意一个数亦或0都等于自身,所以b = b^ (a^ b) = b^ b^ a = 0^a = a。

    再来看第三步,a = a^ b;此时,a = (a^ b)^a;(第一个a为原来的a,值为5;第二个a代表的是第二步运算,其实是交换后的b的值,这里的b也是指的是为交换之前的b),所以,a = b;(b为交换之前的b),所以两数就会发生交换。

    应用三:求整数的绝对值

    int i = a>>31;
    System.out.println(i == 0? a : (~a + 1));

    说明:对于一个整数a,a>>31,若a为正数,a>>31的值为0,若a为负数,a>>31的值为-1。当 i 的值为0时,也就是当a为正数的时候,直接就输出a本身;当 i 的值为-1时,说明a为负数,输出负数的反码 + 1,也就是这个数的绝对值。

    应用四:变换符号

    int a = 45;
    int b = -9;
    System.out.println(~a + 1);
    System.out.println(~b + 1);
    输出结果为-45 9,即变换了正负号。

    应用五:求两个数的平均值

    两个数相加有时候可能相加之后的值超出了对应类型的范围,当然可以采用大数进行处理,但是还有一种方法可以处理,

    (x&y)+((x^y)>>1);
    如下

    package com.demo;
    
    public class WeiYunSuan {
        public static void main(String[] args){
            System.out.println(Integer.valueOf("11111111111111110010110",2));
            System.out.println(Integer.valueOf("11111111111111010001111",2));
            System.out.println((8388502 + 8388239)/2);
            int a = 8388502; //a对应的十进制
            int b = 8388239; //b对应的十进制
            System.out.println((a&b) + (a^b)>>1);
            System.out.println(Integer.valueOf("11111111111111100010010",2));
    
        }
        // a   11111111111111110010110
        // b   11111111111111010001111
        // a&b 11111111111111 01000 0110
        // a^b 00000000000000 100011001
        // a^b>>1 1000 1100
        // a&b + a^b>>1  11111111111111
        // 010000110
        //  10001100
        // 11111111111111100010010
    }
    

    执行结果:

         8388502
         8388239
         8388370
         4194255
         8388370
    

    说明了可以采用这种方法进行两个数平均值的求解

    应用六:取余运算

    对于 a%b,当b为2的n次方的时候 a%b等价于a&(b-1)

    应用七:取int型变量的第k位

    a>>(k-1)&1;运算顺序为先右移k-1位,在与1

    应用八:从x位到y位共有多少个1
    package com.demo;
    
    public class WeiYunSuan {
        public static void main(String[] args){
            int a = 23;
            int sum = 0;
            System.out.println(new Integer(a).toBinaryString(a));
            for(int i = 1; i <= 4; i++)
                sum += a>>(i-1)&1;
            System.out.println(sum);
        }
    }
    

    结果:

     10111
     3
    
    应用九:取末k位

    a&((1<<k) - 1),当结果长度不够时,应该在最左端加上相应的0就可以了

    总结
    功能                示例         位运算
    去掉最后一位    (101101->10110) x >> 1
    在最后加一个0    (101101->1011010)   x < < 1
    在最后加一个1    (101101->1011011)   x < < 1+1
    把最后一位变成1    (101100->101101)    x | 1
    把最后一位变成0    (101101->101100)    x | 1-1
    最后一位取反    (101101->101100)    x ^ 1
    把右数第k位变成1    (101001->101101,k=3)    x | (1 < < (k-1))
    把右数第k位变成0    (101101->101001,k=3)    x & ~ (1 < < (k-1))
    右数第k位取反    (101001->101101,k=3)    x ^ (1 < < (k-1))
    取末三位    (1101101->101)  x & 7
    取末k位    (1101101->1101,k=5) x & ((1 < < k)-1)
    取右数第k位    (1101101->1,k=4)    x >> (k-1) & 1
    把末k位变成1    (101001->101111,k=4)    x | (1 < < k-1)
    末k位取反    (101001->100110,k=4)    x ^ (1 < < k-1)
    把右边连续的1变成0    (100101111->100100000)  x & (x+1)
    把右起第一个0变成1    (100101111->100111111)  x | (x+1)
    把右边连续的0变成1    (11011000->11011111)    x | (x-1)
    取右边连续的1    (100101111->1111)   (x ^ (x+1)) >> 1
    去掉右起第一个1的左边    (100101000->1000)   x & (x ^ (x-1))
    判断奇数        (x&1)==1 
    判断偶数        (x&1)==0(类似x%2)
    清零最低位的1      x&(x-1)
    得到最低位的1      x&-x
    

    摘录原文地址:https://jcoffeezph.top/%E4%BD%8D%E8%BF%90%E7%AE%97%E5%8F%8A%E5%85%B6%E5%B8%B8%E7%94%A8%E6%93%8D%E4%BD%9C.html

    链接2:https://juejin.im/post/5cd4c1db518825357f3203e2

    相关文章

      网友评论

          本文标题:java位运算常用操作

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