参考
- developer.mozilla.org/zh-CN/docs/…
- cnodejs.org/topic/5bbd9…
- juejin.cn/post/690071…
- fengmumu1.github.io/2018/06/30/…
用法
按位左移运算符 <<,用法 a << b,意思是将a的二进制形式向左移动b(b < 32)个比特位,左边超出的位数会被清除,右边会被补零。
举例
9 << 2 得出36(9*2^2)
9(十进制): 00000000000000000000000000001001 (二进制)
9 << 2(十进制): 00000000000000000000000000100100 (二进制) = 36 (十进制)
得出结论:任意数字x
移动至左边y
位,得出
工作案例
动画数据中有一个挂载层,挂载层上记录了多个挂载点,每个挂在点都可以显示隐藏,为了最大限度减小数据体积。用二进制的方式记录挂载点的显隐信息(visible)。
初始visible: 000000000000000000000000000000 (二进制) = 0
第0个挂载点显示: 1 << 0: 000000000000000000000000000001 (二进制)
增加一个挂载点后的visible1(visible | 1 << 0 ): 000000000000000000000000000001 (二进制) = 1
第1个挂载点显示: 1 << 1: 000000000000000000000000000010 (二进制)
增加两个挂载点后的visible2(visible1 | 1 << 1): 000000000000000000000000000011 (二进制) = 3
依此类推
问题
今天遇到一个bug,当挂载点超过30个,保存第31个挂载点的时候,visible信息错了。1 << 31 = -2147483648。
原因
Js 是按64位浮点数存储和表示数字的,能表示整数范围是 -2^53 - 2^53
是所有的按位操作符的操作数都会被转成补码形式的有符号32位整数。最左边的比特位为符号位(sign bit)。
解决方案
使用BigInt,同样可以使用除>>>
(无符号右移)的操作符
BigInt
是一种内置对象,它提供了一种方法来表示大于2^53 - 1
的整数。这原本是 Javascript中可以用Number
表示的最大数字。BigInt
可以表示任意大的整数。
1n << 31n 得 2147483648n
BigInt("1") << 31n