-
前言:
Js存储Number类型,无论是浮点数还是整数,都是采用的双精度存储(64)位,因为位操作符不能操作64位的,所以会先转成32位的整数。
计算机在存储整数的时候都是以补码的形式存储的,正数的补码就是本身,负数是反码+1。
位运算
1、~ : 按位非(NOT)
2、& : 按位与(AND)
3、| : 按位或(OR)
4、^ : 按位异或(XOR)
5、<< : 左移
6、>> : 有符号右移
7、>>> : 无符号右移
一、(~)按位非(NOT)
按位非~会将数值的32位二进制的每一位取反(0变为1,1变为0)。按位非的操作符的本质取操作数负值,然后减1。
拿10举例:
0000 0000 0000 0000 0000 0000 0000 1010 // ~ NOT 1111 1111 1111 1111 1111 1111 1111 0101
~10 = -11
~10.6 = -11
~-1 = 0
使用场景:向下取整
~~-1.5 = -1.5
~~1.5 = 1.5
二、(&)按位与(AND)
按位与&, 本质上将两个操作数的32位二进制数的每一位对齐。然后按如下的规则取值,1 & 1 等于 1; 1 & 0 等于 0;0 & 1 等于0;0 & 0等于0。
两个都是1则为1,否则为0.
举例10&5 = 0
0000 0000 0000 0000 0000 0000 0000 1010 // & AND 0000 0000 0000 0000 0000 0000 0000 0101 // 等于 0000 0000 0000 0000 0000 0000 0000 0000
这个使用场景不多
三、(|)按位或(OR)
按位与|, 本质上将两个操作数的32位二进制数的每一位对齐。然后按如下的规则取值,1 | 1 等于 1; 1 | 0 等于 1;0 | 1 等于1;0 | 0等于0。
有一个为1,就为1,否则为0.
举例10|5 = 15
0000 0000 0000 0000 0000 0000 0000 1010 // & OR 0000 0000 0000 0000 0000 0000 0000 0101 // 等于 0000 0000 0000 0000 0000 0000 0000 1111
常用场景:
取整,和按位非的作用一样
按位与,任何数与0都为那个数字,1|0等于1,0|0等于0,那么我们知道按位操作的时候会转为32位整数,运算过之后才存储到64位中,那么我们就可以根据这一点来进行取整,因为转成32位整形会舍掉小数部分.
0|0=0
0.6|0 = 0
-1.2|0 = -1
四、(^)按位异或(XOR)
按位异或^, 本质上将两个操作数的32位二进制数的每一位对齐。然后按如下的规则取值,1 ^ 1 等于 0; 1 ^ 0 等于 1;0 ^ 1 等于1;0 ^ 0等于0。
两个一样就为0,不一样就为1;
举例10^5=15
0000 0000 0000 0000 0000 0000 0000 1010 // ^ XOR 0000 0000 0000 0000 0000 0000 0000 0101 // 等于 0000 0000 0000 0000 0000 0000 0000 1111
常用场景:
1.不使用额外的空间交换两个数(一般用第三方变量或es6的结构赋值)
在了解这个之前先了解两个准则
(1)两个相同的数进行按位异或等于0
(2)任意一个数与0进行按位异或等于自身
// 两个都是整数时可以使用 let a = 2; let b = 3; a = a^b; b = a^b; a = a^b; console.log(a, 'a'); // 3 console.log(b, 'b'); // 2
五、(<<)左移
左移(<<)将32位二进制向左移动指定的位数,空缺的位将会使用0填充。左移不会影响符号位。
举例:将5左移2位 5<<2= 20
使用场景
乘法
左移是乘法,移动的位数是2的幂数
1<<0=1
1<<1=2
1<<2=4
-1<<2=-4
-1.2<<2=-4
六、(>>)有符号右移
右移(>>)将32位二进制向右移动指定的位数,但是保留符号位,右移空缺的符号位使用0填充。符号位0代表正数,1代表负数
举例:将31有符号右移3位,等于3。 31>>3=3
0|000 0000 0000 0000 0000 0000 0001 1111 // >>3 0|000 0000 0000 0000 0000 0000 0000 0011
使用场景
除法
右移是除法,移动的位数是2的(幂数 × -1)
2>>0 = 2
2>>1=1
4>>2=1
8>>3=1
-2>>1=-1
-2.6>>1=-1
七、(>>>)无符号右移
无符号位右移,会将所有32位数都向右移动。对于正数来说右移和无符号位右移的结果是一致的。
举例:将-31无符号右移28位。
1111 1111 1111 1111 1111 1111 1110 0001
// 负数的表示方法是反码+1
1000 0000 0000 0000 0000 0000 0001 1110 // -30-1=-31 // >>> 28 0000 0000 0000 0000 0000 0000 0000 1111 // 15
-