java中常用的位运算_java位运算常用操作

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<

总结

功能 示例 位运算

去掉最后一位 (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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值