每天一个劝退小技巧之位操作
为什么要使用位操作,因为位操作是直接操作二进制数,是所有语言中执行效率最高的运算。
以下代码以 JavaScript 为例,部分代码在所有支持位操作的语言通用。
注:JavaScript 中数值以 IEEE 754 双精度浮点数表示。
快速取整:
parseInt(2.2) === ~~2.2 // true
parseInt('1.3') === ~~'1.3' // true
1<<30 === ~~1<<30 // true
Math.floor(1.2) == 1.2 | 0
Math.floor(1.2) == 1.2 ^ 0
Math.floor(-1.2) == -1.2 | 0
Math.floor(-1.2) == -1.2 ^ 0
// HINT
parseInt('4294967296') === ~~4294967296 //false, 越界
parseInt('4294967296') === ~~'4294967296' //false, 越界
快速累加
-~undefined === 1 // true
-~0 === 1 // true
-~1 === 2 // true
-~-1 === 0 // true, -~-1 为 -0
-~2<<30 === 2<<29+1 //false
是否奇数
1 & 1 === 1 // 1 为奇数
2 & 1 === 0 // 0 为偶数
3 & 1 === 1 // etc.
权限
// 比如我有 2 3 4 号权限
permission = 1 << 2 | 1 << 3 | 1 << 4
// 现在判断我有没有 3 号权限
hasPerssion3 = !!(permission & 1 << 3) // res is 8, true
hasPerssion5 = !!(permission & 1 << 5) // res is 0, false
hasPerssion0 = !!(permission & 1 << 0) // res is 0, false
注意最大边界为 1 << 30
, 更大需要用 BigInt
获取数组中只出现一次的数字
- 交换律:a ^ b ^ c <=> a ^ c ^ b
- 任何数于0异或为任何数 0 ^ n => n
- 相同的数异或为0: n ^ n => 0
let res = 0
arr.forEach(i => res ^= i)
// return res
0-1互转
0^1 == 1
1^1 == 0
两数中点
left + ((right - left) >> 1) === (left + right) / 2 // int
持续更新,有更好的用法欢迎评论区指出