任何编程语言都提供了二进制数据的与、或、非位操作逻辑,JavaScript也不例外。下面首先介绍JS中的位运算接口(位运算符)
位运算符
| 操作 | 用法 | 描述 |
|---|---|---|
| 按位与 | a & b | 在a,b的位表示中,每一个对应的位都为1则返回1,否则返回0 |
| 按位或 | a | b | 在a,b的位表示中,每一个对应的位,只要有一个为1则返回1,否则返回0 |
| 按位异或 | a ^ b | 在a,b的位表示中,每一个对应的位,两个不相同则返回1,相同则返回0 |
| 按位非 | ~a | 反转被操作数的位 |
| 左移 | a << b | 将a的二进制串向左移动b位,右边移入0 |
| 算术右移 | a >> b | 把a的二进制表示向右移动b位,丢弃被移出的所有位 |
| 无符号右移 | a >>> b | 把a的二进制表示向右移动b位,丢弃被移出的所有位,并把左边空出的位都填充为0 |
算法中位运算符的妙用
求中位数
在二分法中,往往有 middle = (left + right) / 2 的情况发生,并且还需要判断 middle 是否是带0.5的小数,而往往都会固定向上或向下取整,需要用到 floor() 方法,位运算符 >> 可以很方便且运算效率更快地解决。
// 合为偶数时
let left = 10, right = 90;
let middle = (left + right) >> 1;
console.log(middle) // 50
// 合为奇数时
let left = 10, right = 91;
let middle = (left + right) >> 1;
console.log(middle) // 50
变量交换
很多语言中的变量交换都是经典的temp = a; a = b; b = temp,在 python 语言中, 变量交换可以直接 a, b = b, a,在ES6的解构赋值中,JavaScript 也可以很方便地进行变量交换:[a, b] = [b, a],除此之外,变量还可以通过异或运算符交换:
let a = 123;
let b = 456;
a ^= b;
b ^= a;
a ^= b;
console.log(a, b); // 456 123
判断奇偶
奇数最右位为1,偶数为0,因此
- 奇数 & 1 = 1
- 偶数 & 1 = 0
console.log(5 & 1); // 1
console.log(4 & 1); // 0
使用注意事项
- 在所有位运算操作中,运算的变量如果不是
number类型,则会隐式转换为该类型
const pureString = 'hello world!'
console.log(~pureString) // -1
const interString = '5'
console.log(~interString) // -6
const boolTrue = true
console.log(~boolTrue) // -2
notice: 之所以会出现~5 === -6的情况,是因为负数是以补码的形式存储的,关系有:负数 === ~正数+1
- 如果变量是
number类型且为浮点数,则小数部分丢失
const floatNumber = 13.14
console.log(~floatNumber) // -14
console.log(floatNumber >> 0) // 13
console.log(floatNumber | floatNumber) // 13
可以利用此特性来轻松完成一些特殊的需求:
let a = 13.14
console.log(a >> 0) // 13
a = -13.14
console.log(a >> 0) // -13
// 如果用Math.floor(),效果不一样
let b = 13.14
console.log(Math.floor(b)) // 13
b = -13.14
console.log(Math.floor(b)) // -14 <- difference