JAVA中的位运算和使用举例
Posted 顧棟
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA中的位运算和使用举例相关的知识,希望对你有一定的参考价值。
JAVA中的位运算和使用举例
如果对二进制码的转换不是很熟悉,建议先看原码 反码 补码 移码。
位运算是一种直接操作二进制位实现计算的方式,效率较高,在算法上会采用位运算。
JAVA支持的位运算符有:
位运算符 | 描述 | 运算规则 |
---|---|---|
<< | 左移 | 将操作符左边的操作数的二进制位全部左移操作符右边数值的位。 |
>> | 右移 | 将操作符左边的操作数的二进制位全部右移操作符右边数值的位,正数高位补0,负数高位补1,低位丢弃。 |
>>> | 无符号右移 | 将操作符左边的操作数的二进制位全部右移操作符右边数值的位,高位补0,低位丢弃。 |
& | 位与 | 当运算符两边操作数二进制形式相同位置的值,逢0得0,其他得1。 |
| | 位或 | 当运算符两边操作数二进制形式相同位置的值,逢1得1,其他得0。 |
^ | 位异或 | 当运算符两边操作数二进制形式相同位置的值,相同得0,不同得1。 |
~ | 位非 | 这个操作比较特别,它只需要一个操作数,将运算符后的二进制数反转,0变1,1变0 。 |
不存在<<<
运算演示
-
<<
:左移,运算符规则是:各二进位全部左移若干位,高位丢弃,低位补0。例如:3 << 2 ,代表将3的二进制表示,左移2位,int型占4个字节,也就是占32位 由右向左
32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 | 位的序号 -------------------------------------------------------------------------------------- | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 | 3的二进制 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 | 3 << 2 =12
左移常被用来做 ∗ ( 2 n ) * (2 ^ n) ∗(2n)的运算,因为直接基于二进制运算,所以左移效率比 ∗ ( 2 n ) * (2 ^ n) ∗(2n)高。以上述例子来讲,左移2位就是 ∗ 2 2 *2^2 ∗22,即 3 ∗ 4 = 12 3*4=12 3∗4=12
-
>>
:右移,运算符规则是:各二进位全部右移若干位,正数高位补0,负数高位补1,低位丢弃。例如: 13 >> 2 = 3,代表将12的二进制表示,右移2位,int型占4个字节,也就是占32位 由右向左
32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 | 位的序号 -------------------------------------------------------------------------------------- | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 | 13的二进制 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 | 13 >> 2 = 3
例如: -13 >> 2 = -3,代表将12的二进制表示,右移2位,int型占4个字节,也就是占32位 由右向左
32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 | 位的序号 -------------------------------------------------------------------------------------- | 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 | -13的二进制 原码 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 0 | -13的二进制 反码 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 | -13的二进制 补码 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 | -13 >> 2 补码 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 | -13 >> 2 反码 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 | -13 >> 2 = -4 原码
如果是非负数和负数且是偶数的数进行右移n位,那么等于 ⌈ / ( 2 n ) ⌉ \\lceil / (2^n) \\rceil ⌈/(2n)⌉的运算
如果是负数且是基数的数进行右移n位,则等于 ⌊ / ( 2 n ) ⌋ \\lfloor / (2^n) \\rfloor ⌊/(2n)⌋的运算
向上取整:比自己大的最小整数;数学符号 ⌈ \\lceil ⌈ ⌉ \\rceil ⌉
向下取整:比自己小的最大整数;数学符号 ⌊ \\lfloor ⌊ ⌋ \\rfloor ⌋ -
>>>
:无符号右移,运算符规则是:各二进制位全部右移若干位,高位补0,低位丢弃。例如: 13 >>> 2
32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 | 位的序号 -------------------------------------------------------------------------------------- | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 | 13的二进制 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 | 13 >> 2 = 3
例如: -13 >>> 2
32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 | 位的序号 -------------------------------------------------------------------------------------- | 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 | -13的二进制 原码 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 0 | -13的二进制 反码 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 | -13的二进制 补码 | 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 | -13 >>> 2 = 1073741820 补码(原码) 最高位是0 为正数,补码即原码
-
&
:位与,运算规则是:当运算符两边相同位置的值,同为1时返回1,其他返回0。例如: 13 & 2
32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 | 位的序号 -------------------------------------------------------------------------------------- | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 | 13的二进制 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 | 2的二进制 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 | 13 & 2 = 0
例如: -13 & 2
32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 | 位的序号 -------------------------------------------------------------------------------------- | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 | -13的二进制 补码 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 | 2的二进制 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 | -13 & 2 = 2
-
|
:位或,运算规则是:当运算符两边相同位置的值,同为0时返回0,其他返回1。例如: 13 | 2
32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 | 位的序号 -------------------------------------------------------------------------------------- | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 | 13的二进制 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 | 2的二进制 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 | 13 | 2 = 15
-
^
:位异或,运算规则是:当运算符两边相同位置的值,相同时返回0,不相同时返回1。例如: 13 ^ 2
32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 | 位的序号 -------------------------------------------------------------------------------------- | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 | 13的二进制 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 | 2的二进制 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 | 13 ^ 2 = 15
例如: 18 ^ 2
32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 | 位的序号 -------------------------------------------------------------------------------------- | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 | 18的二进制 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 | 2的二进制 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 | 18 ^ 2 = 15
例如: -13 ^ 2
32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 | 位的序号 -------------------------------------------------------------------------------------- | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 | -13的二进制 补码 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 | 2的二进制 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1 | -13 ^ 2 补码 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 | -13 ^ 2 反码 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 | -13 ^ 2 = -15原码
-
~
:位非,这个操作比较特别,他只需要一个操作数,将运算符后二进制数反转,0变1,1变0 。例如: ~13
32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 | 位的序号 -------------------------------------------------------------------------------------- | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 | 13的二进制 | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 0 | ~13的补码 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1 | ~13的反码 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 | ~13=-14的原码
例如: ~-13
32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 | 位的序号 -------------------------------------------------------------------------------------- | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 | -13的二进制 补码 | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 | ~-13=12的补码
使用场景
-
奇偶数
奇数的二进制的第一位(最低位)是1,那么通过 ( n & 1 ) = = 0 (n \\& 1)==0 (n&1)==0为true则为偶数
-
数的交换
交换A与B
a ^= b; b ^= a; a ^= b;
-
对 2 n 2^n 2n的数值进行取模计算
a % 2 n a \\% 2^n a%2n 等价于 a & ( 2 n − 1 ) a\\&(2^n-1) a&(2n−1)
-
生成第一个大于等于a的满足 2 n 2^n 2n的数
static final int MAXIMUM_CAPACITY = 1 << 30; /** * 生成第一个大于等于a的满足2的n次方的数 */ static final int tableSizeFor(int cap) // 整体思想是通过移位和或运算,计算出cap二进制中比cap大且与2的n次方的二进制相差1的数。从出现1的最高位,往最低位方向,通过或运算进行位上的0变1的的方式进行计算,int型一共32位,1+2+4+8+16=31,这边一共移动了31位。而 cap - 1是为了处理边界 int n = cap - 1; n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; n |= n >>> 8; n |= n >>> 16; return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
整体思想是通过移位和或运算,计算出cap二进制中比cap大且与2的n次方的二进制相差1的数。从出现1的最高位,往最低位方向,通过或运算进行位上的0变1的的方式进行计算,int型一共32位,1+2+4+8+16=31,这边一共移动了31位。而
cap - 1
是为了处理边界。当cap是8的时候,这个方法的应该返回8,但是如果不-1
,会返回16。 -
对 2 n 2^n 2n的数值进行乘法计算
a ∗ 2 n a*2^n a∗2n等价于 a < < n a<<n a<<n
-
求相反数
( a + 1 ) (~a+1) ( a+1)
-
求绝对值
a > > 31 = = 0 ? a : ( a + 1 ) a >> 31 == 0 ? a : ( ~ a + 1) a>>31==0?a:( a+1)
以上是关于JAVA中的位运算和使用举例的主要内容,如果未能解决你的问题,请参考以下文章