【Java基础】位运算备忘

192 阅读3分钟

Java位运算

快速备忘

符号描述运算规则
&两个位都是1,结果才为1
|两个位都是0,结果才为0
异或相同为0,相异为1
~0变1,1变0
<<左移符号位不变,数据位左移,高位丢,低位补0
>>右移符号位不变,数据往右移,低位丢,高位补充符号位
>>>无符号右移全部数据往右移动,溢出的低位丢弃,高位补充0。

数字运算规则

位运算的基础

计算机在运算时是以二进制进行数字运算,准确的说,是用补码的格式进行运算。以下简单介绍一下补码的规则,以Java语言的int类型为例。

int

int类型,占4个字节,每个字节等于8个二进制位,即用32个二进制表示一个int数据。下面以数字7和-17为例。

原码

最高位为符号位,0表示正数,1表示负数。直接将十进制转换为二进制。

7 : 0000 0000 0000 0000 0000 0000 0000 0111

-17: 1000 0000 0000 0000 0000 0000 0001 0001

反码

正数和原码相同。负数符号位不变,其他在==原码==基础上按位取反(1变0, 0变1)

-17: 1111 1111 1111 1111 1111 1111 1110 1001

补码

正数和原码相同。负数符号位不变,其他在==反码==基础上+1

-17: 1111 1111 1111 1111 1111 1111 1110 1010

逻辑运算(与/或/非/异或)

与、或

最常用的运算符&|,注意与常用的&&||是不同的,后者是短路与、或。

举例:(a == 1) | (b == 2)左右两边的表达式都会进行判断,而短路或判断前面的表达式为true,就不会判断右边的了。

或者叫取反,这里面唯一一个单目运算符。

异或

相异为1,相同为0。

位移运算

左移<<

符号位不变,数据往左移动,低位补0,溢出的高位丢弃。

a << n,a左移n位,相当于乘以 2^n^,注意左移太多位会溢出。

右移>>

符号位不变,数据往右移动,溢出的低位丢弃,高位补充符号位

a >> n,a右移n位,相当于乘以2^1/n^。注意结果不是整数的右移,如1 >> 10 = 0; 5 >> 1 = 2,这里就不详细解释了。

无符号右移>>>

数据往右移动,溢出的低位丢弃,高位补充0。

正数效果和右移一样,负数则不同。

小技巧

你可以不用,但是你得能看懂

奇偶性判断

n & 1 == 1 ? 奇数 :偶数

1的补码是0000 .... 0001,即最后一位是1,其余都为0

无论正负,奇数最后一位一定1,奇数最后一位前面的所有位 &1与之后都是0。所以可以根据最后一位是不是1来判断是不是奇数。

乘除

乘2的n次方,数a乘以2的n次方,a << n;

判断一个数是否是2的n次方, a & (a - 1) == 0;

交换两个整形数字

a = a ^ b;
b = a ^ b;
a = a ^ b;

但是要特别注意,如果写一个函数交换数组中的两个值,可能会下意识的这么写

void swap(int[] num, int i, int j){
        num[i] = num[i] ^ num[j];
        num[j] = num[i] ^ num[j];
        num[i] = num[i] ^ num[j];
}

这样写是有问题的,因为当i == j时,会出现为0的情况。加个判断就好