简朴相识位运算
简朴相识基本
位运算符是在数字底层(示意数字的32个数位)上举行操纵的。
一切整数字面量都是有标记整数,用31位示意数值,用第32位示意标记,0示意正数1示意负数。数值局限从-(2^31 – 1)到(2^31 – 1)。注重位0的位置在最右边。
0是一切位为0
-1是一切位为1
-2147483648是除了最左侧为1,其他都是0
2147483647是除了最左侧为0外,其他都是1的整数。
正数是以真二进制情势存储的,前 31 位中的每一位都示意 2 的幂,从第 1 位(位 0)最先,示意 2^0,第 2 位(位 1)示意 2^1。没用到的位用 0 添补,即忽略不计。
var num = 18;
(num).toString(2); //10010(18 = 2^4+2^1)
负数也存储为二进制代码,不过采纳的情势是二进制补码
直接来例子,求-18的补码
(1)求该数字非负版本的二进制。这里也就是18的二进制(10010)
(2)求二进制反码,也就是1变成0,0变成1(1111 1111 1111 1111 1111 1111 1110 1101)
(3)在反码的基本上加一,注重二进制里的运算1+1=10(1111 1111 1111 1111 1111 1111 1110 1110)
然则呢,ECMAScript并不以这类二进制补码来示意负数,而是用数字绝对值的规范二进制代码前面加上负号的情势输出。
//诺,就是如许
var num = -18;
(num).toString(2); //-10010,“-18的显现就是如许的”
位运算符
与 & 两个都为1 效果才为1
坚持数位对齐,用上述划定规矩然后举行与运算。
或 | 两个都为0时,效果才为0
坚持数位对齐,用上述划定规矩然后举行或运算。
非 ~ 0变1,1变0
实在就是对数字求负,然后减一
var num = 25;
var num1 = ~num;
num1; //-26
异或 ^ 两个相同为0,不同为1
满足交流律,一个数和自身异或的效果是0,任何数x与0异或的效果都是自身x,任何数x与-1异或的效果都是-x。
左移 << 各二进位悉数左移多少位,高位抛弃,右边低位补0
var old = 2; //10
var new = old << 5; //1000000
右移 >> 各二进位悉数右移多少位,有标记数,用标记位的值添补这些空位。
一些小技能
(1)推断奇偶(貌似很有用啊)
//平常都是(i % 2 !== 0)来推断奇数
if(i & 1) {
//奇数须要举行的事变
} else {
//偶数须要做的事变
}
(2)交流两个数字
平常须要一个中心变量,
var temp = a;
var a = b;
var b = temp;
能够用位操纵符完成交流不须要中心变量
a ^= b; //a = a ^ b
b ^= a; //b = b ^ a = b ^ a ^ b = a (b = a)
a ^= b; //a = a ^ b = a ^ b ^ a = b;
(3)变更标记
只须要求反后加1即可
function rever (n) {
return ~n + 1;
} //11 => -11
(4)求绝对值
关于负数对其取反后加1来获得正数。先移位获得标记位i >> 31
var i = a >> 31 //假如a为正数,i为0。假如a为负数,i为-1
return i == 0 ? a : (~a + 1); //正数坚持稳定,负数变更标记。
另一种方法
能够经由过程异或,参考异或的划定规矩。a与i异或后减i(即加0或许加1)
var i = a >> 31;
return (a ^ i) - i;