Js
bitwise operator
底层库开发中可使用的二进制代替Math类操作,会提速,但失去语义话
二进制各位为 1 其他为 0 代表的数
所以往左一位就是 x 2,往右一位就是 %2
<<:左移(右边0,保留符号位),<< 1 相当于 x2
-2 << 1 //-4
3 << 1 //6
>>:右移(左边补符号位,其他补0,相当于移位后还是负数), >> 1 相当于 %2
对于正数的右移操作优先使用 >>>,因为可省去符号位操作,理论更快。
-2 >> 1 //-1
-2 >>> 1 //2147483647
与 >> 的不同在于,左边全补0,包括符号位 所以负数的符号位没有被保留 被 0 补充,对于 正数 来说没有任何区别,较小负数 >>> 会变为一个很大的正数,因为负数越小 1 位越多
| 0:去小数位,注意与 Math.floor 对负数处理对区别
1.23|0 //1
-1.2323 | 0 //-1
Math.floor(1.23) //1
Math.floor(-1.23) //-2
^ 1 / ^= 1:0,1切换
0 ^ 1 //1
1 ^ 1 //0
0 ^= 1 //0
1 ^= 0 //1
!~-1:-1判断,-1带小数当然也为 true
因为 1 为: 0000 … 0001
所以-1作为1的补码表示为: 1111 … 1111 全为1,所以按位非后全为 0,也就是 0,falsy
!~-1 === true
& 1:奇变1 偶变0 ,所以 !!(number & 1) 可以用于判断是否为奇
121 & 1 //1
2 & 1 //0
!!(121 & 1) //true
交换数
因为 ^ 操作相当于左右自有 1 位的集合 (只有一边为 1 ,保留 1,都为 1 或 都为 0 则为 0);
第一步相当于收集所有自有 1,二三步相当于舍弃所有自有 1 位,使用对方 1 位和 共有 1 位,所以实现了交换。
let a = 1; b = 2;
a = a^b;
b = a^b; // 1
a = a^b; // 2
加法
自有(只有当前操作数为 1 的位)共有(左右操作数都为 1 的位)
正数加法的本质就是 l r异或取 合位1,l r与取 进位1 ,再左移去进位,循环处理(异或取合位)进位,直到不再需要进位 合,所以可以简单得到:
^:获得左右 ,自有1位(无进位)
&:获得左右,共有1位(等待进位)
function add(l, r) {
while(r !== 0) {
let temp = l;
l = l ^ r; // 合(合1 未处理进位)
// & 获取需要进位的位(两数同位 为1)
// 左移1完成进位, & 后为0说明无需进位(没有同位1的位)
r = (temp & r) << 1; // 取进位,循环处理直到处理完所有进位
}
return l;
}
减法
减法就是 a - b -> a + (-b)
其实就是 右侧转符号,再相加,负数是正数的 全位取反 + 1,所以正数也是负数的 全位取反 + 1,也就是如下处理:
function minus(l, r) {
r = add(~r, 1)
return add(l, r);
}