[js] 位运算
- js位运算的运行效率偏低(大概意思就是比你自己手动改都慢,虽然这个快慢比较也是ms级的)。
- js默认把整数当做32位处理。
- js中的数字默认是有符号的。
10进制转换成2进制
numObj.toString([radix])
toString() 方法返回指定 Number 对象的字符串表示形式。
(1).toString(2)//1 也就是01
(2).toString(2)//10
(3).toString(2)//11
2进制转换成10进制
parseInt(string, radix)
parseInt() 函数将给定的字符串以指定基数(radix/base)解析成为整数。
parseInt(1,2)//1
parseInt(10,2)//2
parseInt(11,2)//3
&
与
都为1为1,其他为0。
2 (0010) & 7 (0111) => 2 (0010)
//二进制计算
01&10 //0也就是00
10&11 //10
1010&1011 //1010
//十进制计算,返回二进制计算后的结果
1&2 //0
2&3 //2
10&11 //10
- 可用于判断奇偶数
0&1 //0
1&1 //1
2&1 //0
3&1 //1
4&1 //0
-1&1 //1
-2&1 //0
这是因为
奇数的二进制码的最后一位数肯定是1,而1只有最后一位为1,按位&操作之后,结果肯定只有最后一位数为1。
而偶数的二进制表示的最后一位数是0,和1进行按位&操作,结果所有位数都为0。
1 = 0001
3 = 0011
--------
& = 0001
- 判断一个数是否为2的n次幂,可以将其与自身减一相与
var number = 4
(number & number -1) === 0 // true
|
或
有1为1,没1为0。
//二进制计算
01&10 //11
10&11 //11
1010&1011 //1011
//十进制计算,返回二进制计算后的结果
1&2 //3
2&3 //3
10&11 //11
- 对正数实现Math.floor()效果
0.1|0 //0
1.2|0 //1
2.4|0 //2
3.5|0 //3
4.6|0 //4
-1.6|0 //-1 //error
-2.4|0 //-2 //error
Math.floor(-1.6) //-2
Math.floor(-2.4) //-3
这是因为
浮点数不支持位运算,所以会先把1.1转成整数1再进行位运算,就好像是对浮点数向下求整。
0001
| 0011
---------
0011
其他效果
null|0 //0
undefined|0 //0
''|0 //0
'xx'|0 //0
^
异或
不同为1,相同为0。
2 (0010) ^ 7 (0111) => 5 (0101)
a = 1 0 1
b = 1 1 0
a ^ b = 0 1 1
//二进制计算
01&10 //11
10&11 //1也就是01
1010&1011 //1也就是0001
//十进制计算,返回二进制计算后的结果
1&2 //3
2&3 //1
10&11 //1
- 可用于互换两个变量的值
var num1 = 1, num2 = 2;
num1 ^= num2; // num1 = num1 ^ num2 = 1 ^ 2 = 3
num2 ^= num1; // num2 = num2 ^ (num1 ^ num2) = 2 ^ (1 ^ 2) = 1
num1 ^= num2; // num1 = num1 ^ num2 = 3 ^ 1 = 2
console.log(num1); // 2
console.log(num2); // 1
~
非
~2(0010) => -3 (1101)
求二进制的反码?
“一个负数的二进制码是该数绝对值的反码+1”?
~1 //-2
~2 //-3
~3 //-4
// 如果url含有?号,则后面拼上&符号,否则加上?号
url += ~url.indexOf("?") ? "&" : "?";
因为:
~-1 === 0
-1在内存的表示的二进制符号全为1,按位非之后就变成了0. 进一步说明——1在内存的表示为: 0000…0001,第一位0表示符号位为正,如果是-1的话符号位为负用1表示1000…0001,这个是-1的原码,然后符号位不动,其余位取反变成1111…1110,这个就是-1的反码表示,反码再加1就变成了1111…1111,这个就是-1的补码,负数在内存里面(机器数)使用补码表示,正数是用原码。所以全部都是1的机器数按位非之后就变成了全为0。剩下的其它所有数按位非都不为0,所以可以利用这个特性可以用来做indexOf的判断。
<<
有符号左移
有符号左移会将32位二进制数的所有位向左移动指定位数。
不会影响符号位。
let num = 2; // 二进制10
num = num << 5; // 二进制1000000,十进制64
- 可用于求2的N次方
1 << 0 //1
1 << 1 //2
1 << 2 //4
1 << 3 //8
1 << 4 //16
x << y
左操作数的值向左移动右操作数指定的位数。相当于将x乘以2的y次方.
>>
有符号右移
有符号右移会将32位二进制数的所有位向右移动指定位数。
不会影响符号位。
let num = 64; // 二进制1000000
num = num >> 5; // 二进制10,十进制2
- 可用于求一个偶数整数的二分之一
2 >> 1 //1
4 >> 1 //2
6 >> 1 //3
102 >> 1 //51
1024 >> 1 //512
x >> y
左操作数的值向右移动右操作数指定的位数,等效于x除以 2的y次方.
>>>
无符号右移
正数的无符号右移与有符号右移结果是一样的。
负数的无符号右移会把符号位也一起移动,而且无符号右移会把负数的二进制码当成正数的二进制码.
let num = -64; // 11111111111111111111111111000000
num = num >>> 5; // 134217726
- 可用于判断是否是正数
1 >>> 0 //1
-1 >>> 0 //4294967295
2 >>> 0 //2
-2 >>> 0 //4294967294
是正数则结果为原数