关于Java中位运算符的理解
1.位运算符认知
这一点算是java基础中的一个黑洞吧,不经常用,可读性也比较差,关键是比较难理解。但最近准备面试的时候看到java源码中用到了很多,看的一脸懵B,逃避不了那就面对它吧!
知识1:Java位运算是针对于整型(byte、char、short、int、long)数据类型的二进制进行的移位操作。
知识2:
数据类型 | 位数 |
---|---|
byte | 8 |
boolean | 8 |
short | 16 |
int | 32 |
long | 64 |
float | 32 |
double | 64 |
char | 16 |
知识3:计算机表示数字正负不是用+ -加减号来表示,而是用最高位数字来表示,0表示正,1表示负 。
2.位运算符实验
看代码就好了
/**
* @author YuanHaiLiang
* @date 2018-08-14
*/
public class bitOperation {
/*
--------------------------------------------------------------------------------------------
\ &:按位与 \ 如果相对应位都是1,则=为1,否则为0 \ (A&B),得到12,即0000 1100\
--------------------------------------------------------------------------------------------
\ |:按位或 \ 如果相对应位都是0,则=为0,否则为1 \ (A | B)得到61,即 0011 1101 \
--------------------------------------------------------------------------------------------
\ ~:按位非 \ 按位取反运算符翻转操作数的每一位,即01互换\ (〜A)得到-61,即1100 0011 \
--------------------------------------------------------------------------------------------
\ ^:按位异或 \ 如果相对应位值相同,则=为0,否则为1 \ (A ^ B)得到49,即 0011 0001 \
--------------------------------------------------------------------------------------------
\ <<左位移运算符 \ 左操作数按位左移右操作数指定的位数。 \ A << 2得到240,即 1111 0000 \
--------------------------------------------------------------------------------------------
\ >>右位移运算符 \ 左操作数按位右移右操作数指定的位数 \ A >> 2得到15即 1111 \
----------------------------------------------------------------------------------------------
\ \ 左操作数的值按右操作数指定的位数右移 \ \
\ >>> 无符号右移 \ 移动得到的空位以零填充 \ A>>>2得到15即0000 1111 \
----------------------------------------------------------------------------------------------
优先级S:~ 波浪
优先级A:<<、>>和>>>
优先级B:&
优先级C:^ shift+6
优先级D:/
*/
public static void main(String[] args) {
/* 60 = 0011 1100 */
/* 13 = 0000 1101 */
int A = 60; int B = 13;
System.out.println( "A&B=" + (A&B) );
System.out.println( "A|B=" + (A|B) );
System.out.println( "~A=" + (~A) );
System.out.println( "~A=" + (A^B) );
System.out.println( "A<<2=" + (A<<2) );
System.out.println( "A>>2=" + (A>>2) );
System.out.println( "A>>>2=" + (A>>>2) );
}
}
结果如下:
A&B=12
A|B=61
~A=-61
~A=49
A<<2=240
A>>2=15
A>>>2=15
3.重点是什么时候用
我为什么要它?
答案1:位运算的运算效率比直接对数字进行加减乘除高很多(至于为什么会快,不明白的可以去搜下为什么C的代码执行速度比Java,python快),代码需要考虑性能的时候
答案2:因为大牛都喜欢这样,估计是炫技吧!
4:使用
场景1:判断奇偶数 a&1 结果为 0 ,a就是偶数 结果为 1 ,a就是奇数
场景2:求平均数 (x+y)/2 这样吗?考虑过 x+y可能超过int的范围吗?正确的姿势是 (x&y)+((x^y)>>1)
场景3:有两个int类型变量x、y,要求两者数字交换,不用临时变量?(当年学java的时候这可是奥数级别的题目) x ^= y; y ^= x; x ^= y;
场景4:求绝对值
int abs( int x ) { int y= x >> 31 ; return (x^y)-y ; //or: (x+y)^y }
场景5:取模 a % (2^n) 等价于 a & (2^n - 1)
场景6:快速乘法 a * (2^n) 等价于 a << n
场景7:快速除法 a / (2^n) 等价于 a >> n
场景8:求相反数 (~x+1)
总之,整型所涉及到的操作它都可以更快速的实现,有兴趣可以仔细研究。