简朴的进修位运算

简朴相识位运算

简朴相识基本

位运算符是在数字底层(示意数字的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;
    原文作者:luckyzv
    原文地址: https://segmentfault.com/a/1190000008601728
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞