js位运算符和使用场景

js位运算符和使用场景


文章目录

  • js位运算符和使用场景
  • 前言
  • 一、(~)按位非(NOT)
  • 二、(&)按位与(AND)
  • 三、(|)按位或(OR)
  • 四、(^)按位异或(XOR)
  • 五、(<<)左移
  • 六、(>>)有符号右移
  • 七、(>>>)无符号右移


前言

这里主要是讲述位操作符和一些常用的使用场景。作为我对位运算符的学习总结。
这里有一些前提的知识需要提前拿出来说一下,我们都知道Js存储Number类型,无论是浮点数还是整数,都是采用的双精度存储(64)位,上一篇文章我也提到了,因为位操作符不能操作64位的,所以会先转成32位的整数,我们都知道计算机在存储整数的时候都是以补码的形式存储的,正数的补码就是本身,负数是反码+1,为什么计算机存储整数的时候要以补码的形式存储呢?因为CPU只有加法运算器,具体细节自行百度。


一、(~)按位非(NOT)

按位非~会将数值的32位二进制的每一位取反(0变为1,1变为0)。按位非的操作符的本质取操作数的负值,然后减一。
~23 === -24
~0 === -1
~100 === -101

拿10举个例子

0000 0000 0000 0000 0000 0000 0000 1010
// ~ NOT
1111 1111 1111 1111 1111 1111 1111 0101

常用场景

  1. 向下取整,注意这里只有>0的数可以用,我们都知道向下取整我们一般用Math.floor(),如图这里可以自己动手算一算。根据上面的规则,如图
    js位运算符和使用场景_第1张图片

  2. Array.indexOf中的使用,我们都知道indexOf会返匹配到第一个的下标,没返回那就返回-1。我们在实际项目中判断都是
    if (‘米莉波比布朗’.indexOf(‘莉’) > -1) {

    }
    如果存在’莉’这个字在执行If里的代码,但这看上去并不是那么的简洁。我们知道Boolean(0)为false,但是Boolean(-1)为ture,所以我们可以 if (~‘米莉波比布朗’.indexOf(‘莉’) ) {} 这样写因为~-1为false,别的都为true。


二、(&)按位与(AND)

按位与&, 本质上将两个操作数的32位二进制数的每一位对齐。然后按如下的规则取值,1 & 1 等于 1; 1 & 0 等于 0;0 & 1 等于0;0 & 0等于0。

(示例)10和5之间进行按位与操作的结果,等于0:


0000 0000 0000 0000 0000 0000 0000 1010
// & AND
0000 0000 0000 0000 0000 0000 0000 0101
// 等于
0000 0000 0000 0000 0000 0000 0000 0000

三、(|)按位或(OR)

按位与|, 本质上将两个操作数的32位二进制数的每一位对齐。然后按如下的规则取值,1 | 1 等于 1; 1 | 0 等于 1;0 | 1 等于1;0 | 0等于0。
(示例)10和5之间进行按位或操作的结果,等于15:

0000 0000 0000 0000 0000 0000 0000 1010
// & OR
0000 0000 0000 0000 0000 0000 0000 0101
// 等于
0000 0000 0000 0000 0000 0000 0000 1111

常用场景

  1. 取整
    按位与,任何数与0都为那个数字,1|0等于1,0|0等于0,那么我们知道按位操作的时候会转为32位整数,运算过之后才存储到64位中,那么我们就可以根据这一点来进行取整,因为转成32位整形会舍掉小数部分,这么一想好像跟~~前面的按位非效果一样啊,是的效果一样。但我取整的时候一般用按位与,如图:
    js位运算符和使用场景_第2张图片

四、(^)按位异或(XOR)

按位异或^, 本质上将两个操作数的32位二进制数的每一位对齐。然后按如下的规则取值,1 ^ 1 等于 0; 1 ^ 0 等于 1;0 ^ 1 等于1;0 ^ 0等于0。
举例:10和5之间进行按位异或操作的结果15。

0000 0000 0000 0000 0000 0000 0000 1010
// ^ XOR
0000 0000 0000 0000 0000 0000 0000 0101
// 等于
0000 0000 0000 0000 0000 0000 0000 1111

常用场景

  1. 不使用额外的空间交换两个数
    在了解这个之前先了解两个准则
    (1)两个相同的数进行按位异或等于0
    (2)任意一个数与0进行按位异或等于自身
// 0
100 ^ 100
// 0
-99 ^ -99

// 100
100 ^ 0
// -2
0 ^ -2

在代码中交换两个变量的值,通常是通过第三个变量,或者使用ES6中的解构赋值

// 使用第三个变量
var a = 1
var b = 2
var c = a
a = b
b = c

// 使用解构赋值
var x = 1
var y = 2
[x, y] = [y, x]

使用异或按位运算符

let a = 2
let b = 3

a = a ^ b
// b = a ^ b ^ b => a ^ (b ^ b) => a ^ 0 = a
b = a ^ b
// a = a ^ b ^ a ^ b ^ b => (a ^ a) ^ (b ^ b) ^ b => 0 ^ 0 ^ b => 0 ^ b = b
a = a ^ b
  1. 经典算法题
    「leetcode」268.缺失数字.

五、(<<)左移

左移(<<)将32位二进制向左移动指定的位数,空缺的位将会使用0填充。左移不会影响符号位。
举例:将5左移2位,等于20。

0|000 0000 0000 0000 0000 0000 0000 0101
// <<2
0|000 0000 0000 0000 0000 0000 0001 0100
// 等于
(2^0 * 0) + (2^1 * 0) + (2^2 * 1) + (2^3 * 0) + (2^4 * 1) = 0 + 0 + 4 + 0 + 16 = 20

常用场景

乘法
左移是乘法,移动的位数是2的幂数

  • 左移1位,等价于,乘以2的1次方。
  • 左移2位,等价于,乘以2的2次方。
  • 左移3位,等价于,乘以2的3次方。

六、(>>)有符号右移

右移(>>)将32位二进制向右移动指定的位数,但是保留符号位,右移空缺的符号位使用0填充。
举例:将31有符号右移3位,等于3。

0|000 0000 0000 0000 0000 0000 0001 1111
// >>3
0|000 0000 0000 0000 0000 0000 0000 0011
// 等于
(2^0 * 1) + (2^1 * 1) = 1 + 2 = 3

常用场景

乘法
右移是除法,移动的位数是2的(幂数 × -1)

  • 右移1位,等价于,乘以2的-1次方。
  • 右移2位,等价于,乘以2的-2次方。
  • 右移3位,等价于,乘以2的-3次方。

七、(>>>)无符号右移

无符号位右移,会将所有32位数都向右移动。对于正数来说右移和无符号位右移的结果是一致的。
举例:将-31无符号右移28位。

1111 1111 1111 1111 1111 1111 1110 0001
// >>> 28
0000 0000 0000 0000 0000 0000 0000 1111
// 等于
(2^0 * 1) + (2^1 * 1) + (2^2 * 1) + (2^3 * 1) = 1 + 2 + 4 + 8 = 15

你可能感兴趣的:(基础,javascript)