前言
原因是在刷 leetcode 的时候因为位运算导致的期待值错误死活无法通过,也增加了一些js中关于位运算的知识。
首先先回顾一下自己所遇到的问题,在使用迭代法解答剑指 Offer 16. 数值的整数次方问题时,发现对于一个测试用例超时:1.00000 -2147483648
本来的解答是:
function myPow(x: number, n: number): number {
let ans = 1;
let exponent = Math.abs(n);
for (let i = exponent; i != 0; i >>= 1, x *= x) {
if (i % 2) {
ans *= x
}
}
return n < 0 ? 1 / ans : ans;
};
于是在循环中加入了一条 console.log(i)
发现 i
变成了负数,最后一直是 -1,导致死循环。
WTF???咋回事。
于是控制台手动计算:
2147483648 >> 1
怎么会这样,******!
但是 num / 2
没问题啊,就先看看2进制吧:
num.toString(2)
// "10000000000000000000000000000000"
num.toString(2).length
// 32
要变成负数,这是无符号右移,说明符号位是1,可是这符号位不是1啊,毕竟 js 中是以 64 位双精度存储。
老老实实先用除法解决问题吧。
后来经过一番搜索,发现自己还是大意了没有闪,没看过标准还是得吃亏,es 标准说 js 中的位运算针对的都是 32 位整型,也就是说 js 在进行位运算操作时,先会将数字转为 32 位的整型,然后再操作。这也就很清楚的解释了刚才所遇到的问题。
注: 第5和第6步清除的说明了情况。
先前自己是知道 js 位运算需要先转换为整数,没想到是 32 位,一直天真的认为是 64 位,这下长记性了。
结论
没有什么必要在 js 中使用位运算,未必就能提高性能,引擎未必不会帮我们优化,由于 number 类型存储的方式,会存在坑。
有的时候用位运算存粹是为了偷懒不想写向下取整,为了少一些麻烦还是尽量避免使用位运算吧。
参考资料
- Javascript: 位操作中的溢出和负数
- 为什么不要在 JavaScript 中使用位操作符?
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!