位运算的黑科技
2017-07-06 本文已影响286人
l_sivan
最近在学NodeJs,然后练手做项目的时候想用下位运算,需求是除2舍小数位,于是想像Java一样,直接除2,发现并不行
console.log(5/2);
sivan@sivan-All-Series:~/workspace/nodejs/interesting_book$ node h.js
2.5
想了下发现很正常,因为JavaScript是弱数据语言,全部的变量都可以用一个var来声明的,所以结果的表现是浮点型,确实很正常。
于是换了一种方式,之间看Java的部分源码看到位运算的相关操作(后面会提),所以在这也试下位运算
console.log(5/2>>1/2);
sivan@sivan-All-Series:~/workspace/nodejs/interesting_book$ node h.js
2
结果一试就不得了了,居然还真的试出来了
而在js的运算符中,算术运算符的优先级是大于移位运算符的,也就是上面的代码可以换成这样
console.log(2.5 >> 0.5);
sivan@sivan-All-Series:~/workspace/nodejs/interesting_book$ node h.js
2
而结果确实一样,觉得很黑科技,居然还能用浮点数做移位运算,右移0.5位?这么黑科技的,于是这个时候,去Java上尝试了一下
Java下的尝试
这边就很正常啦,因为Java里面,整数之间进行运算,得到的数还是整数,也就是上面的图片实际上相当于(2 >> 0)
于是测试下
换成浮点型 换成整型
可见确实如同猜测一样
于是,结合Java里出现的情况,对JS中的情况做了个猜测,js在有算术运算和移位运算同时存在的情况下,会将算术运算的结果转成整型再运算
下面验证下猜测
console.log(5/2>>1/2);
console.log(2.5 >> 0.5);
console.log(5/2 >> 0);
console.log(2 >> 1/2);
console.log(5.9/2 >> 0);
console.log(2 >> 0);
如无意外,这一批的log的结果,都会是2
sivan@sivan-All-Series:~/workspace/nodejs/interesting_book$ node h.js
2
2
2
2
2
2
结果确实如同预料般。
那这个位运算有啥用呢?
首先
哈哈哈,起码知道,在JS中想得到除以某个数舍小数位,只要右移或者左移0位就行了,像console.log(5/2 >> 0);---->2
这样。
除了这个发现之外,其实位运算确实挺方便的,比如
想要放大或者缩小2的N次幂的倍数,只要左移或者右移N位就行了
移几位这个可能会迷糊,其实联想下十进制就行了,500右移一位变成50,缩小了10倍,右移两位变成5,缩小了100倍也就是10的2次幂,所以无论什么进制都一样,移动N位,就变化进制的N次幂
其次还有一个,如何快速得到某个数最接近的偏大2的次幂数,比如15--16,16--16,17--32
答案就在HashMap的源码
重点是n |= n >>> N
这几行代码,画个图就懂了
因为进行了多次|=运算的运算,所以可以确保从最高位到最低位都是1,也就是值为2的N次方-1
其中因为java中int的长度为32为,所以有
n |= n >>> 16;
,这样就能确保数很大的时候都能每一位都做过|=运算
总结
其实位运算的骚操作还有很多,只不过水平有限,计算机组成原理学的也不怎么样,所以这些其实也只是小打小闹。
水平有限,难免有错,还请诸君指正。