Skip to main content

位运算在js中的使用

· 2 min read
wang bo
早睡早起

原码、反码、补码 以及位运算符在js中的使用


0.1 + 0.2 ≠ 0.3 ?#

最近看了一道浮点数精度的题,0.1 + 0.2 不等于0.3,这个问题不只是js才会发生 甚至还有人专门建立个网站解释这种情况 https://0.30000000000000004.com/

  • 因为0.1和0.2在 十进制 转 二进制 时出现了无线循环的情况
  • eg:0.1(10) = 0.000110011001100…(2)

在IEEE 754运算标准中提出了一种使用近似值表示小数的方式,并且引入了精度的概念。

形成0.1 + 0.2 不等于 0.3 的原因是 0.1 + 0.2 两个近似值相加,结果也是个近似值。

解决浮点数精度问题方法 (.1 + .2).toFixed(2)

数学与计算机中的加减#

计算机只认识0和1这种二进制的数据,而数学中常用到十进制,想要使用计算机进行数学计算的话,原码、反码、补码这个概念就浮出来了。

原码#

  • 正为0,负为1;
    • 10 的 原码为 0 1010 ,-10的源码为 1 1010
  • 原码计算问题:加法没问题,减法出错
    • 10 - 2:0 1010 + 1 0010 = 1 1100 = -12

反码#

  1. 正数的反码不变,负数为符号位不变 其余位取反。
  2. 运算完的结果:如果为正数则不变,为负数符号位不变 其余取反。
10 - 2:0 1010 + 1 0010         = 0 1010 + 1 1101(-2的反码)         = 0 0111 + 1(进位)        = 0 1000         = 82 - 10:0 0010 + 1 1010        = 0 0010 + 1 0101(-10的反码)        = 1 0111        = 1 1000(值为负数,除符号位 其余取反)        = -88 - 7:0 1000 + 1 0111        = 0 1000 + 1 1000(-6的反码)        = 0 0000 + 1(进位)        = 0 0001        = 1

但是还有一个问题 0 0000 和 1 0000 代表的 -0 和 0 都是 0,所有引出了补码。

补码#

正数不变,负数除符号位取反 再+1。如果有进位则省略

10 - 10:0 1010 + 1 1010           = 0 1010 + 1 0110 (取反,再+1)           = 0 0000 (有进位但省略)           = 0

总结#

1在内存的表示为: 0000...0001,第一位0表示符号位为正,如果是-1的话符号位为负用1表示1000...0001,这个是-1的原码,然后符号位不动,其余位取反变成1111...1110,这个就是-1的反码表示,反码再加1就变成了1111...1111,这个就是-1的补码,负数在内存里面(机器数)使用补码表示,正数是用原码。

位运算符在js中的应用#

1. 如果url含有?号,则后面拼上&符号,否则加上?号#

url += ~url.indexOf("?") ? "&" : "?";

2. 使用异或交换两个数的值#

交换两个数的值一般使用额外的变量来帮助交换,也可以使用异或的方式进行数值交换: 0⊕0=0,1⊕0=1,0⊕1=1,1⊕1=0(同为0,异为1),这些法则与加法是相同的,只是不带进位。 异或的方式:

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

3. 使用与去掉低位或者高位#

let a = 0b01000110; // 十进制为70let b = 0b10000101; // 十进制为133只判断后四位:a & 0b00001111 < b & 0b00001111 // true

4. 使用与&来进行权限判断#

后台管理系统中有些操作只允许一、二级管理员操作,有些操作只允许一、三级管理员操作。 用位来表示管理权限,一级用第3位,二级用第2位,三级用第1位,即一级的权限表示为0b100 = 4,二级权限表示为0b010 = 2,三级权限表示为0b001 = 1。如果A操作只能由一级和二级操作,那么这个权限值表示为6 = 0b110,它和一级权限与一下:6 & 4 = 0b110 & 0b100 = 4,得到的值不为0,所以认为有权限,同理和二级权限与一下6 & 2 = 2也不为0,而与三级权限与一下6 & 1 = 0,所以三级没有权限。这里标志位的1表示打开,0表示关闭。 这样的好处在于,我们可以用一个数字,而不是一个数组来表示某个操作的权限集,同时在进行权限判断的时候也很方便。

5.位运算符在react中的应用#

// 从当前上下文中移除上下文AcurContext &= ~A;
// 是否处在A上下文中 false(curContext & A) !== NoContext
// 找出当前最高优先级的更新在哪一位function getHighestPriorityLane(lanes) {  return lanes & -lanes;}

参考文献#