位运算
JavaScript 中的位运算是将操作数视为 32 位元的二进制串,返回标准的 JavaScript 数值。
JavaScript 中数值都由 64 位浮点数存储,但在两个整数进行位运算时,会转化为 32 位的有符号整数。
所以在计算机中,数字是有穷的,在 JavaScript 中也是有穷的。
所以有一个安全数的概念。所谓安全数就是在这个范围内都存在一正一反一一对应。
JavaScript 的安全数在 ES6 中是 Number.MAX_SAFE_INTEGER。
但位运算只针对 32 位整数。对于浮点小数会先转化为 32 位的二进制串,在进行计算。
位运算符
Operator | Usage | 位运算符 |
---|---|---|
按位与 ADD | a & b | a 和 b 对应位都为 1 则返回 1,否则返回0 |
按位或 OR | a | b |
按位异或 XOR | a ^ b | a 和 b 对应位相同返回 1,否则返回 0 |
按位非 NOT | ~a | a 中每一位取反 |
左移 shift | a << b | 将 a 的二进制串向左移动 b 位,右边填充 0 |
算术右移 | a >> b | 将 a 的二进制串向右移动 b 位,丢弃移出的所有位 |
无符号右移 | a >>> b | 将 a 的二进制串向右移动 b 位,丢弃移出的所有位,并把左边空出的位用 0 填充 |
位运算技巧
左移 & 右移
左移以为相当于乘于二,右移一位相当于除于二并向下取整(不是向 0 取整)。
let a = 2
console.log(a << 2) // 8 = 2 * 2 * 2
console.log(a >> 2) // 0 = Math.floor(2 / 2 / 2)
复制代码
异或
异或运算有两种理解方式
- 相同为 1,不同为 0
- 不进位相加
异或运算满足交换律和结合率
0 异或任何数都为该数本身,一个数异或它自己为 0
let a = 8
console.log(a ^ a) // 0
console.log(a ^ 0) // 8
复制代码
通过异或还可以实现不使用额外空间交换值
let a = 8
let b = 7
a = a ^ b
b = a ^ b
a = a ^ b
console.log(a, b) // 7, 8
复制代码
但是这个方法有一个限制,a , b 的内存地址必须保证不一样,否则会返回 0
提取最右侧的 1
let a = 9
let rightOne = a & (~a + 1)
console.log(parseInt(a).toString(2), parseInt(rightOne).toString(2)); // 1001 1
复制代码
获取一个数二进制的某一位
// 获取 a 的第 b 位,最低位为 0
function getBit(a, b) {
return (a >> b) & 1
}
console.log(parseInt(getBit(15, 2)).toString(2)); // 1
复制代码
将一个二进制数的某一位设置为 0
// 将 a 的第 b 位设置为 0 ,最低位编号为 0
function unsetBit(a, b) {
return a & ~(1 << b)
}
复制代码
将一个二进制数某一位设置为 1
// 将 a 的第 b 位设置为 1 ,最低位编号为 0
function setBit(a, b) {
return a | (1 << b)
}
复制代码
将一个二进制某一位取反
// 将 a 的第 b 位取反 ,最低位编号为 0
function flapBit(a, b) {
return a ^ (1 << b)
}
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END