[Performance] 二进制与性能优化

二进制基础知识

1. 二进制表示数

image-20251027170330859

一个格子 --> bit(位):计算机中最小的存储单位

2 个bit

image-20251027212024356

种类数:22 = 4

数的范围:0~3(0~22 - 1)

8 个 bit 一组:byte:计算机中最小的访问单位

种类数:28 = 256

数的范围:0~255(0~28 - 1)

2. 反码与补码

n 个格子:

种类数:2n

数的范围:0~2n - 1

拿最左边的位作为符号位:0 就是正数,1 就是负数

image-20251027213339217

1 个 byte(8位)

  • 无符号位:0~28 - 1(0~255)
  • 有符号位:-27 ~ 27 - 1(-128 ~ 127)

1000 000 代表的就是 -128

二进制 十进制
00000000 0
00000001 +1
... ...
01111111 +127
10000000 -128 ← 只有这一个
10000001 -127
... ...
11111111 -1

负数具体的二进制表示:反码和补码

反码:将二进制数的每一位进行反转,1 --> 0, 0-->1

补码:反码的基础上 +1

补码特点:

  1. 零只有一种:0000 0000,而1000 000 不是负0,而是-128
  2. 正数的补码和源码相同,负数补码源码取反+1
  3. 计算机底层都是采用补码来做计算
7
原码:0000 0111
补码:0000 0111
-3
 3源码:0000 0011
-3源码:1000 0011
-3反码:1111 1100
-3补码:1111 1101

3. 位相关操作

操作符 名称 说明
& 按位与(AND) 两个对应位都为 1 时结果为 1
` ` 按位或(OR)
^ 按位异或(XOR) 对应位不同时为 1,相同时为 0
~ 按位取反(NOT) 每一位取反(0→1, 1→0)
<< 左移(Left Shift) 向左移动位,右边补 0
>> 有符号右移(Sign-propagating Right Shift) 向右移动位,左边补符号位
>>> 无符号右移(Zero-fill Right Shift) 向右移动位,左边补 0

1. 按位与

5 & 3

101
011
---
001

2. 按位或

5 | 3

101
011
---
111

3. 按位异或

不同的时候为1,相同为0

5 ^ 3

101
011
---
110

4. 按位取反

~5

101
---
010

5. 左移:左移后右边补0

5 << 1

0000 0101
---------
0000 1010

6. 右移

  1. 有符号:右移的时候,左边补充符位

    10 >> 1
    0000 1010
    ---------
    0000 0101
    
    -10 >> 1
    1111 0110
    ---------
    1111 1011
    
  2. 无符号:直接左边补充0,这意味结果一定是一个非负数

    10 >>> 1
    0000 1010
    ---------
    0000 0101
    
    -10 >> 1
    1111 0110
    ---------
    0111 1011
    
    -8 >> 2
    1111 1001
    ---------
    0011 1110
    

二进制特性与性能优化

特性1:如果二进制数的第 0 位为 1,则该数字为奇数,如果第 0 位为 0,则该数为偶数

3: 0000 0011
4: 0000 0100
5: 0000 0101
6: 0000 0110
7: 0000 0111

判断一个数 num 是否为偶数

num % 2 === 0

现在:

num & 1 === 0
0000 0011
0000 0001
---------
0000 0001
0000 0100
0000 0001
---------
0000 0000

计算机底层,只有加法。

减法:7 - 4 转换 7 + (-4)

乘法:2 * 3 转换 2 + 2 + 2

除法:12 / 6 转换 12 - 6 - 6

取余:7 % 3 转换 7 - 3 - 3

特性2:如果二进制数的低 n 位都是 0,则该数可以被 2n 整除

十进制 二进制 低位情况 能否被整除
4 0000 0100 低 2 位为 0 能被 2²=4 整除
8 0000 1000 低 3 位为 0 能被 2³=8 整除
12 0000 1100 低 2 位为 0 能被 2²=4 整除
10 0000 1010 低 1 位为 0 能被 2¹=2 整除

从右往左依次代表 2⁰、2¹、2²、2³……

如果一个数的低 n 位全是 0,意味着它的二进制结构中没有包含 2⁰ 到 2ⁿ⁻¹ 这些成分,因此它一定是 2ⁿ 的倍数。

// 判断 num 是否为 2ⁿ 的倍数
function isDivisibleByPowerOfTwo(num, n) {
  return (num & ((1 << n) - 1)) === 0;
}

(1 << n) 表示的是 2ⁿ,1 << 3 表示 23

0000 0001(1)
---------
0000 1000(8)

(1 << n) - 1) 生成低 n 位全为 1 的掩码

(1 << 3) - 1

0000 0001
---------
0000 1000
---------
0000 0111

掩码就是一种遮盖

1011 0110(值)
0000 1111(掩码)
0000 0110(结果)

特性3:如果二进制数除了第 n 位为 1,其它为均为 0,那么该数等于 2ⁿ

二进制表示 唯一为 1 的位 该位代表的值 十进制结果
0000 0001 第 0 位 2⁰ 1
0000 0010 第 1 位 2
0000 0100 第 2 位 4
0000 1000 第 3 位 8
0001 0000 第 4 位 2⁴ 16

判断一个数是否为 2 的幂次方

function powerOfTwo(n) {
  if (n < 1) return false;
  while (n % 2 === 0) {
    n = n / 2;
  }
  return n === 1;
}
function powerOfTwo(n) {
  return n > 0 && (n & (n - 1)) === 0;
}

n - 1 会把 n 的最低位的那一个 1 变成 0,同时把其右边所有位变成 1。之后再和 n 本身做按位与运算,若结果为 0,说明 n 只有一位是 1(即 2 的幂)。

下面是一些验证示例:

n 二进制 n-1 n & (n-1) 结果
1 0000 0001 0000 0000 0000 0000 ✅ 2⁰
2 0000 0010 0000 0001 0000 0000 ✅ 2¹
3 0000 0011 0000 0010 0000 0010
4 0000 0100 0000 0011 0000 0000 ✅ 2²
6 0000 0110 0000 0101 0000 0100
8 0000 1000 0000 0111 0000 0000 ✅ 2³

特性4:将二进制数左移 n 位约等于乘以 2ⁿ,右移 n 位约等于除以 2ⁿ

去除小数

3.9 ---> 3

  1. 负数的结果有问题 Math.floor(-3.9)--> -4
  2. 效率不高

JS 中位操作的特性,JS 中的所有数字都以 64 位浮点数(双精度) 存储,但在执行位操作时,会临时转换为 32 位有符号整数,运算完成后再转回 64 位浮点数作为结果。这意味着:

  • 位运算的结果始终是一个 32 位整数;
  • 小数会被截断;
  • 超过 32 位的部分会被丢弃。
3.9 | 0
~~3.9

交换两个数

let a = 5;
let b = 3;
let c = a;
a = b;
b = c
[a, b] = [b, a]
a = a + b;
b = a - b;
a = a - b;
a = a ^ b;
b = a ^ b;
a = a ^ b;

二进制业务应用场景

权限管理

if(value === A){
  // ...
} else if (value === B){
  // ...
}
image-20251028171940144

该情况下就可以使用二进制。

权限关系:

下载 打印 查看 审核 详细 删除 编辑 创建
0 0 0 0 0 0 0 0

0:没有此权限

1:有此权限

0000 0001:只有创建权限

0010 0011:查看、编辑、创建权限

添加权限

当前:0000 0011(创建和编辑)

开放查看权限:0010 0000

当前权限 | 查看权限

0000 0011
0010 0000
---------
0010 0011

删除权限

做异或操作

当前:0010 0011

取消编辑权限:0000 0010

0010 0011
0000 0010
---------
0010 0001

判断是否拥有一个权限

做按位与操作:如果返回值是权限值本身,就代表有这个权限,如果返回的是0,代表没有这个权限

当前:0011 1100(查看、审核、详细、删除)

是否有创建权限

0011 1100
0000 0001
---------
0000 0000

是否有查看权限

0011 1100
0010 0000
---------
0010 0000
posted @ 2026-02-09 14:07  Zhentiw  阅读(11)  评论(0)    收藏  举报