位运算
数据在计算机中都是以01的形态进行存储,位运算可以直接对01进行操作,其效率自然很高,在Java源码中是很常见的。这里总结位运算的概念以及常见的操作,后续遇到会补充。
位运算符
位运算是需要使用位运算符的,位运算符有如下几种(本表以java
语言中的位运算为标准):
含义 | 符号 | 简述 |
---|---|---|
按位与 | a & b | 同一得 1 |
按位或 | a | b | 有一得 1 |
按位异或 | a ^ b | 相同得 0 |
按位取反 | ~a | 取反 |
左移 | a << b | 向左移动,低位补零,高位舍弃 |
带符号右移 | a >> b | 向右移动,高位补原有高位,低位舍弃 |
无符号右移 | a >>> b | 忽略符号位,空位都以0补齐 |
位运算优先级
~的优先级最高,其次是<<、>>和>>>,再次是&,然后是^,优先级最低的是|。
位运算符在日常开发中也是 有许多应用场景的,具体场景将在下边代码中展示:
按位或 |
/**
* | 按位或 有一得1
* 比较m, n之间,换成二进制后谁的1最多
* 使用 按位或 | 计算 有一得一,与&清零不同的是使用 | 可以置1
* @param m
* @param n
*/
public static int test2(int m ,int n) {
// 7:111 8:0001 7|8 = 111(2) | 0001(2) = 1111(2) = 15
// 6:011 7:111 6|7 = 011(2) | 111(2) = 111(2) = 7
while ((m | m+1)<=n) {
m = (m | m+1);
}
return m;
}
按位与 &
/**
* & 按位与 同一得1
* 判断一个整数n是不是2的x次幂
* 若n&(n-1)=0 则说明n是2的x次幂
* 也可以这样说:循环结束后当ans=1时,说明n时2的x幂
* 按位与 & : 同一得一,可用于清零操作
* @param n
* @return ans 表示n转化成二进制数之后,1的个数
*/
public static int test1(int n) {
int ans = 0;
while (n != 0) {
ans++;
n &= (n-1);
System.out.println(n);
}
return ans;
}
异或 ^
/**
* ^ 异或 相同得0
* 可用于交换两个变量的数值,不用到带三个变量
* 交换律
* @param a , b
*/
public static void test3(int a, int b) {
a = a ^ b;
// a^b ^ b = a
b = a ^ b;
// a^b ^ a = b
a = a ^ b;
}
按位取反~
/**
* 取反 ~
* 先对原数进行按位取反,然后减1,再进行取反得到一个数,最后加上负号即可
*
* 00000000 00000000 00000000 00000100 原值
* 11111111 11111111 11111111 11111011 取反
* 11111111 11111111 11111111 11111010 -1
* 00000000 00000000 00000000 00000101 取反
*/
public static void test4() {
int a = 4;
System.out.print(~4);
}
左移 <<
/**
* 左移 <<
*
* 00000000 00000000 00000000 00000101 左移2位后,低位补0
* 00000000 00000000 00000000 00010100 转为十进制为 20
*/
public static void test5() {
int a = 5;
System.out.print(a << 2);
}
右移 >>
/**
* 右移 >> 高位补符号位
*
* 00000000 00000000 00000000 00000101 右移2位后,高位补0
* 00000000 00000000 00000000 00000001 转为十进制为 1
*/
public static void test6() {
int a = 5;
System.out.print(a >> 2);
}
无符号右移 >>>
/**
* 无符号右移 >>> 高位补0
*
* >>>和>>的区别是:在执行运算时,>>>运算符的操作数高位补0,而>>运算符的操作数高位移入原来高位的值。
*
*/
public static void test7() {
/** 负数取值: 减一后按位取反 **/
/**
* -5 >> 2 情况
* 11111111 11111111 11111111 11111011 -5 的二进制
* 11111111 11111111 11111111 11111110 >> 2
* 10000000 00000000 00000000 00000010 减1,按位取反,值为-2
*/
System.out.println(-5 >> 2);// 结果是-2
/**
* -5 >>> 2 情况
* 11111111 11111111 11111111 11111011 -5 的二进制
* 00111111 11111111 11111111 11111110 >>> 2, 高位补0,此时为正数
*/
System.out.println(-5 >>> 2);// 结果是1073741822
}
本文来自博客园,作者:mingshan,转载请注明原文链接:https://www.cnblogs.com/mingshan/p/17793495.html