1.对2的指数次方取余--hash的求模实现
一个数n对2的k次方取余,等于对这个数减一做与运算。
n%(2^k) = n & (2^k-1)
所以,在HashMap的源码中,数组的长度不管怎么扩容都要属于2的次方,是因为要确定键值对的桶位时,是用key求出来的hash值,对其长度取余,然后就用到了这个,桶号index = hash & ( length - 1).
2.交换两个数值--异或
a = a ^b ; b = a ^ b ; a = a ^ b ;
0异或任何得不变,1异或任何取反,异或自身得0,即异或一个数两次不变。
异或还可以用来判断两个数符号是否相同,相同得正,不同得负,注意0的情况
不过交换数值的话,a=a+b;b=a-b;a=a-b; 感觉比较直观。
3.取反--常见计算题
0对应-1,1对应-2,记住对应关系就行了,正的反的都是这样。
取反不管符号,直接找对应的数是什么。
n+1—— -(~n)
n-1 —— ~(-n)
-n —— ~n+1
4.判断一个数的2进制表示中,1的个数
n&(n-1)会去掉n的二进制中最右边的那个1,因此可以通过这个性质来做。
这个表达式还能用来判断一个数是否是2的n次方,如果是的话,其结果会为0。
5.判断奇偶数
n&1,很简单,判断最后一位即可。
6.左移右移
和5一样,如果要手写代码,不妨用进一些能用到的地方。
箭头指向哪边,朝哪边移。
>>n右移n位,除2^n,两个箭头是有符号右移,高位会自动补相应的0或1,>>>n是无符号右移,高位补0的。
所以i=1<<31;(i=-2^31)
i=i>>>1;(i=2^30)
<<m左移m位,乘2^m,左移不存在符号问题,低位自动补0.
6.java操作位运算可能用到的方法
Integer的静态方法toBinaryString(int i),返回i的二进制的字符串表示。
后续?……
补一个直观二进制合集,编译运行后直观看很容易回想起int的二进制存储形式
System.out.println("0: "+Integer.toBinaryString(0));
System.out.println("-1: "+Integer.toBinaryString(-1));
System.out.println("-2^31 (int~-max): "+Integer.toBinaryString(1<<31));
System.out.println("2^31-1(int~+max): "+Integer.toBinaryString((1<<31)-1));
System.out.println("8: "+Integer.toBinaryString(8));
System.out.println("32: "+Integer.toBinaryString(32));
System.out.println("-8: "+Integer.toBinaryString(-8));
System.out.println("-32:"+Integer.toBinaryString(-32));
7.对二进制位的操作
从低位到高位,取n的第m位
n>>(m-1) & 1
从低位到高位,将n的第m位置1
n | (1<<(m-1))
从低位到高位,将n的第m位置0
n & ~(1<<(m-1))
8.&与&&区别
int x=0,y=4;
for(int z=0;z<3;z++,x++)
{
if(x>1&++y<10)
{ ++y; }
}
System.out.println(y);
这道题我一开始想差了,第一时间我想到的考点就是&&运算,如果前面一个false,就不进行后面的判断了,然后我又想到Java里另一个知识点,就是boolean类型不能自动转换成int类型,这就是while(n--)在C++里可以当n次循环,但Java不行的原因,因为n不能被转成boolean当作true.(byte等会先转成int,然后再在int的二进制形式里截取所需长度转回去(如果不是+=这类运算,需要强转))
所以我一开始以为两个boolean类型不能做&运算,还以为题目出错了。
结果是我错了,乱用了知识点,忘记了boolean不是一样在底层用1byte来存嘛,那就可以做&运算嘛,并且&的运算是两边都会进行的,结果自然是两边true才为true。所以这题结果是8;如果是&&的话就是6.
9.
……