被遗忘的位运算符

85 阅读3分钟

Date: 2017-04-01

前言

整数:ECMAScript整数包括有符号整数(允许正数和负数)和无符号整数(只允许正数),在ECMAScript中,所有整数字面量默认都是有符号整数

  • 有符号整数:数值范围从-2147483648到2147483647

  • 无符号整数:数值范围从0到4294967295

var i = 18,  j = -18;
alert(i.toString(2));  // -> '10010'
alert(j.toString(2));  // -> '-10010'

位运算符NOT(~)

1、把运算符转为32位二进制数字

2、再转为它的二进制反码

3、把二进制反码转为浮点数

简:对数字求负,然后减1,比如~25 === -26

位运算符AND(&)

它对数字的二进制进行操作,把数字转换为二进制后,把每个数字的数对齐,不够补0,然后以下面的规则进行OR运算:

1 对 1 -> 1

1 对 0 -> 0

0 对 1 -> 0

0 对 0 -> 0

因此, 16 & 15 = 0, 15 & 14 = 14

16:  10000
15:  01111
----------------
00:  00000
00:  0
15:  01111
14:  01110
----------------
00:  01110
00:  14

位运算符OR(|)

它对数字的二进制进行操作,把数字转换为二进制后,把每个数字的数对齐,不够补0,然后以下面的规则进行AND运算:

1 对 1 -> 1

1 对 0 -> 1

0 对 1 -> 1

0 对 0 -> 0

因此, 16 | 15 =16, 15 | 14 = 15

16:  10000
15:  01111
----------------
00:  11111
00:  16
15:  01111
14:  01110
----------------
00:  01111
00:  15

左移运算(<<)

有符号右移运算(>>)

无符号右移运算(>>>)

用例

“4”的整数次幂(链接:web.jobbole.com/86290/)

给定一个32位有符号整数(32 bit signed integer),写一个函数,检查这个整数是否是“4”的N次幂,这里的N是非负整数。不使用常规循环和遍历

思路:利用二进制位数 和 位运算符 & 解决

40 = 1B
41 = 100B
42 = 10000B
43 = 1000000B

也就是每个数比上一个数的二进制后面多两个零嘛。最重要的是,“4”的幂的二进制数只有 1 个“1”。判断一个二进制数只有 1 个“1”,只需要:

(num & num - 1) === 0

但是,二进制数只有 1 个“1”只是“4”的幂的必要非充分条件,因为“2”的奇数次幂也只有 1 个“1”。所以,我们还需要附加的判断:

(num & num - 1) === 0 && (num & 0xAAAAAAAA) === 0

为什么是 num & 0xAAAAAAAA === 0? 因为这个确保 num 的二进制的那个 “1” 出现在“奇数位”上,也就确保了这个数确实是“4”的幂,而不仅仅只是“2”的幂

最终结果:

function isPowerOfFour(num) {
  return num > 0
      && (num & (num-1)) === 0
      && (num & 0xAAAAAAAA) === 0;
};