上一章咱们学习了按位操做符 带你认识按位操做符html
这一章咱们整理一下按位运算的经典案例markdown
使用按位操做符的数,会先转成 32 位比特序列,也就是32 位的有符号的整数app
若是这个数是正数,若是大于 ,只会保留低 32 位, 高于 32 位的数不存储;函数
若是这个数是负数,若是小于 ,只会保留低 32 位, 高于 32 位的数不存储;oop
按位与(&)
两个二进制数, 它们对应位的数都是 1 时, 结果为 1, 不然, 结果为 0。post
12.12 & 12.12 //12
Math.PI & Math.PI //3
复制代码
JavaScript 默认将数字存储为 64 位浮点数,但按位运算都是以 32位的二进制整数执行。学习
两个相同的数按位运算后, 结果只会保留整数部分,小数部分在转行阶段不存储。spa
Infinity & Infinity //0
Number.MAX_VALUE & Number.MAX_VALUE //0
复制代码
若是一个数大于 因为按位运算时只会保留低 32 位运算, 高于 32位的数丢弃, 结果就不许确了。code
function assert(x) {
return x & 1;
}
assert(3) //1 若是返回1是奇数,不然是偶数。
复制代码
x 是任意正整数,这里咱们用 x = 3举例子,那么, 3 & 1
转成32 位比特序列就是:orm
3 (base 10) = 00000000000000000000000000000011 (base 2)
1 (base 10) = 00000000000000000000000000000001 (base 2)
--------------------------------
3 & 1 (base 10) = 00000000000000000000000000000001 (base 2) = 1 (base 10)
复制代码
3 & 1
的结果是 1,是奇数。咱们再来一个例子:
4 (base 10) = 00000000000000000000000000000100 (base 2)
1 (base 10) = 00000000000000000000000000000001 (base 2)
--------------------------------
4 & 1 (base 10) = 00000000000000000000000000000000 (base 2) = 0 (base 10)
复制代码
4 & 1
的结果是 0,是偶数。
编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 '1' 的个数(也被称为 汉明重量).)。
function hammingWeight(x) {
count = 0
while(x){
x = x & (x - 1);
count++;
}
return count;
}
hammingWeight(6) //2
复制代码
这里咱们用x = 6带入, 那么 x - 1 = 5, 5 & 6
的结果是多少, 咱们画图理解。
6 (base 10) = 00000000000000000000000000000110 (base 2)
5 (base 10) = 00000000000000000000000000000101 (base 2)
--------------------------------
6 & 5 (base 10) = 00000000000000000000000000000100 (base 2) = 4 (base 10) count++;
3(base 10) = 00000000000000000000000000000011 (base 2)
--------------------------------
4 & 3(base 10) = 00000000000000000000000000000000 (base 2) = 0 (base 10) count++;
复制代码
咱们一共执行了两次x = x & (x - 1)
, 因此也会执行两次count++
, 第三次开始执行 while 时, x = 0
, 跳出循环,返回结果 2
;
经过画图理解, 由于二进制是满 2 进 1,因此 x & (x - 1)
刚好能够把x 的二进制位中的最低位的 1 变成 0。 每次都会把二进制 x 中的一个 1 变成 0 , 统计执行x & (x - 1)
异或的次数, 就是 “1” 的个数。
x & n - 1
, 总能把x最低位的 1变为 0, 其余位保持不变。