java中位操作_Java中使用位操作的几个小技巧

一、判断整数的奇偶性

按照传统的思路,判断一个整数的奇偶性是通过用这个数与2求模,看运算结果是否为0。学了位运算符以后,我们可以换一种思路来考虑问题。我们知道:Java语言中,所有数字存储在内存中,都要先转换成补码的形式。任何一个偶数用补码表示出来后,它的最后一个二进制位都是0,而奇数补码的最后一个二进制位都是1。

所以,我们可以通过判断这个整数的补码的最后一位二进制数是0还是1,来判断这个数是偶数还是奇数。判断的方法就是:

用这个数与1进行按位与的操作:

如果结果为0,那么这个数就是偶数,

否则就是奇数。

0aae00f60fd7

与操作判断奇偶性

如果大家不理解这个算法的原理,请看下图:

0aae00f60fd7

image

为了方便表述,我们把要判断奇偶性的数字称为a。图中,以横线为界,分别展示了a为偶数和奇数的情况下,与数字1进行按位与操作的结果。其中,上面的二进制串是a的补码,下面二进制串是数字1的补码。可以看到,数字1被转换成补码之后,总共有32位,其中前31位都是0,最后1位的值是1。这就导致a补码的前31位无论是0还是1,与数字1的补码进行按位与运算,运算结果的前31位都只能是0,决定最终运算结果的就只有a补码最右边的那个二进制位。如果最右边那一位是0,那么a就是偶数,a与1按位与运算的最终结果是数字0。反过来,如果最右边那一位是1,那么a就是奇数,a与1按位与运算的最终结果是数字1。因此我们只要看一下a与数字1进行按位与运算的结果就知道a的奇偶性了。具体的程序实现如下:

0aae00f60fd7

二、求绝对值

常规算法求绝对值的思路是:首先判断一个数a是否>=0,如果a>=0,则返回a本身,否则返回a的相反数。这个过程包含判断和选择两个步骤。如果使用位运算符来实现求绝对值,可以省略掉判断的步骤,直接返回运算结果。下面来讲解一下使用位运算符求绝对值的基本原理。我们知道:任何一个二进制位上的数,与0进行异或运算,运算的结果都与这个二进制位上的数相同。把这个结论扩展一下,从原来某个数的单独的一个二进制位扩展到这个数字本身,可以得出另外两个结论,第一个结论:任何一个整数与0进行异或运算后依然保持不变。如果小伙伴不理解的话,请看下图,我们以数字5作为例子分析讲解:

0aae00f60fd7

image

另一个结论:任何一个整数与-1进行异或运算后再加上1,得到的结果就是这个数的相反数。如果不理解的话,还是看下图,仍然是以数字5分析讲解:

0aae00f60fd7

image

以上两个结论中,第一个结论比较容易理解。我们简单的解释一下第二个结论的原理。第二个结论能够成立的关键就在于,数字-1用补码的形式表示出来,恰好是一个32位全为1的二进制串。这个二进制串与任何一个其他二进制串进行按位异或运算,都可以达到”取反”的效果,而按照补码的计算规则,一个正数按位取反后再加1,得到的就是它相反数。比如图中的数字5,按位取反之后,再加1得到的就是-5。

至此,我们已经知道怎样通过位运算的方式获得一个数的相反数了。在《Java语言位运算符详解》一文中还讲过:int类型的正数经过带符号右移31位之后,得到的必然是0,而负数经过带符号右移31位得到的是-1。我们就可以通过右移所得到的这个0或者-1,判断出这个数是正数还是负数。知道数字的正负属性,然后再用位运算的方式得到这个数本身或者是它的相反数,就能求出这个数的绝对值。按照这个思路,我们就可以来编写求绝对值的程序了,程序如下:

0aae00f60fd7

image

示例程序中的变量a是int型,如果改为long型,对a带符号右移63位也可有相同的运算效果。

三、数字判重

同样是利用了二进制数的性质:xyy = x。我们可见,当同一个数累计进行两次xor操作,相当于自行抵销了。例如在Leetcode上有这么一道算法题:

0aae00f60fd7

image

0aae00f60fd7

image

由于不重复的数字只有一个,因此连续的xor操作会自行抵销了重复数,剩下的就是不重复的数。

四、数值交换

使用^=实现数字交换,不需要借助中间变量。

int a = 11;

int b = 22;

// 开始交换

a ^= b;

b ^= a;

a ^= b;

// 交换完成

执行后的结果:

a=22

b=11

五、判断数字符号是否相等

使用 ^ 判断符号是否相同,如果结果>=0,则表示数字的符号相同。

(a ^ b) >= 0; // true 相同; false 不相同

六、判断 2 的整数幂

n & (n - 1) // 如果为 0,说明 n 是 2 的整数幂

···

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值