Javascript 位运算及运用

Javascript 位运算

参考:巧用JS位运算

ECMAScript 整数有两种类型,即有符号整数(允许用正数和负数)和无符号整数(只允许用正数)。在 ECMAScript 中,所有整数字面量默认都是有符号整数。

数18的表示方法

数18表示

18 的二进制版本只用了前 5 位,它们是这个数字的有效位。把数字转换成二进制字符串,就能看到有效位:

var iNum = 18;
alert(iNum.toString(2));    //输出 "10010"

正数的源码反码补码相同

负数也存储为二进制代码,不过采用的形式是二进制补码。计算数字二进制补码的步骤有三步:

  1. 确定该数字的非负版本的二进制表示(例如,要计算 -18的二进制补码,首先要确定 18 的二进制表示)

  2. 求得二进制反码,即要把 0 替换为 1,把 1 替换为 0

  3. 在二进制反码上加 1

1. ~ 按位取反运算

var v3 = ~8;

 console.log(v3);// -9

// 8 的二进制有效位
00...00 1000 
// 按位取反后
11...11 0111
//补码-1 在按位取反得到负数数值
00...00 1001'


var v3 = ~-9;
console.log(v3);//8
    

应用1: 使用按位非~判断索引存在

// 如果url含有?号,则后面拼上&符号,否则加上?号
url += ~url.indexOf("?") ? "&" : "?";

2. &与运算

将进行操作的对应的二进制位分别进行与运算后将结果返回。

  var v = 1 & 5;

console.log(v); // 1

应用1:利用& 判断奇偶数

 var a =(i)=>i&1?console.log(i+"是奇数"): console.log(i+"是偶数");

应用2:使用按位与&去掉高位

let a = 0b01000110; // 十进制为70
let b = 0b10000101; // 十进制为133
//现在认为他们的高位是没用的,只有低4位是有用的,即最后面4位,为了比较a,b后4位的大小,可以这样比较:
a & 0b00001111 < b & 0b00001111 // true

3.| 或运算

将进行操作的对应的二进制位分别进行或运算后将结果返回。

var v = 1 | 7;
console.log(v);// 7
var v = 1 | 8;
console.log(v);// 9

4. ^异或运算符

将进行操作的对应的二进制位分别进行异或运算后将结果返回。

 var a = 1^2;
 console.log(a);//3

应用1:使用异或交换两个数

let a = 5,
    b = 6;
 
a = a ^ b;
b = a ^ b; // b 等于 5
a = a ^ b; // a 等于 6

5. << 左移运算符

将操作数对应的二进制进行左移,右侧空出来的用零补填。

var a = 3<<2;
console.log(a);//12

6. >> 右移运算符

有符号右移>> 和 左移运算互为逆运算
var a = 3<<2;
console.log(a);//12
无符号右移>>> 将符号位一起移动

位运算的综合应用

不使用加减乘除来做加法,经常用来考察对位运算的掌握情况。读者可以先自行尝试分析和实现。

不能用加减乘除,意思就是要你用位运算进行计算。以实际例子说明,如a = 81 = 0b1010001,b = 53 = 0b0110101。通过异或运算,我们发现异或把两个数相加但是不能进位,而通过与运算能够知道哪些位需要进位,如下所示:

 1010001
^ 0110101
 ---------
  1100100

  1010001
& 0110101
 ---------
  0010001

把通过与运算得到的值向左移一位,再和通过异或得到的值相加,就相当于实现了进位,这个应该不难理解。为了实现这两个数的相加可以再重复这个过程:先异或,再与,然后进位,直到不需要再进位了就加完了。所以不难写出以下代码:

function addByBit(a, b) {
  if (b === 0) {
    return a;
 }
// 不用进位的相加
    let c = a ^ b;
  // 记录需要进位的
 let d = a & b;
 d = d << 1;
   // 继续相加,直到d进位为0
   return addByBit(c, d);

}
let ans = addByBit(5, 8);

console.log(ans);

位运算还经常用于生成随机数、哈希,例如Chrome对字符串进行哈希的算法是这样的:

uint32_t StringHasher::AddCharacterCore(uint32_t running_hash, uint16_t c) {
  running_hash += c;
  running_hash += (running_hash << 10);
  running_hash ^= (running_hash >> 6);
  return running_hash;

}

不断对当前字符串的ASCII值进行累加运算,里面用到了异或,左移和右移。

你可能感兴趣的:(Javascript 位运算及运用)