使用二进制来表示步骤完成进度
一、原因
日常项目中可能会遇到的场景,比如
1、记录用户完成的多个步骤
2、用户提交信息后,后台审核驳回的多个原因字段
...
这些如果用多个字段表示会非常麻烦,而且不好记,多余
我们可以使用二进制的形式来包含不同的状态
二、使用方式
/**
* description:根据 二进制转换成的 10 进制,经过对比得到下一个未完成的步骤
* @param {Number} stepBinaryToTenHex 二进制转换的10进制值
* @param {Number} maxStep 最大可记录步骤数,默认为 8
* */
function calcNextStep(stepBinaryToTenHex, maxStep = 8) {
// 默认步数为第 1 步
let power = 1
for (let step = 1; step <= maxStep; step++) {
if ((stepBinaryToTenHex & power) === 0) {
// 若 `与操作` 结果为 0
// 说明当次步骤还未完成,返回该步骤
return step
}
// 若 `与操作` 结果不为 0,说明是已完成
// 继续增大 2 的幂次方
power *= 2
}
}
完成第一步:0000 0001 --> 1 calcNextStep(1) // 下一个未完成步骤为:2
完成第二步:0000 0011 --> 3 calcNextStep(3) // 下一个未完成步骤为:3
完成第三步:0000 0111 --> 7 calcNextStep(7) // 下一个未完成步骤为:4
完成第四步:0000 1111 --> 15 calcNextStep(15) // 下一个未完成步骤为:5
完成第五步:0001 1111 --> 31 calcNextStep(31) // 下一个未完成步骤为:6
完成第六步:0011 1111 --> 63 calcNextStep(63) // 下一个未完成步骤为:7
完成第七步:0111 1111 --> 127 calcNextStep(127) // 下一个未完成步骤为:8
完成第八步:1111 1111 --> 255 calcNextStep(255) // undefined
注意:
stepBinaryToTenHex 才是前端和后端存储的值,并不是直接使用二进制保存
三、原理
1. 表示
用 0000 0000 表示 1 - 8 个步骤
从右到左,依次表示 第 1 步 到 第 8 步 的完成情况
二进制位上为 1 的表示该步骤已经完成,为 0 表示未完成
1: 0000 0001
2: 0000 0011
3: 0000 0111
4: 0000 1111
5: 0001 1111
6: 0011 1111
7: 0111 1111
8: 1111 1111
假如:我们此时走到第四步
// step 为 4
// stepBinary 二进制 为 00001111
// stepBinaryToTenHex 为 15
4: 00001111
2. 计算
那么我们想知道还未开始的 step 是多少?
可以使用 与操作(&)
与操作的规则是
0 & 0 = 0
0 & 1 = 0
1 & 1 = 1
下面是 2 的递增次方值,转换成 2 进制 powerBinary 后都只有一个 1
根据 与操作 的特点,我们可以将 stepBinary 与 powerBinary 进行 与操作
得到的结果为 0,则说明该步没有完成
1: 0000 0001
2: 0000 0010
4: 0000 0100
8: 0000 1000
16: 0001 0000
32: 0010 0000
64: 0100 0000
128: 1000 0000
3. 例子
比如 第 4 步相应的的二进制和 powerBinary 依次 与操作
4: 0000 1111
2^1: 0000 0001 --> 结果为: 0000 0001
2^2: 0000 0010 --> 结果为: 0000 0010
2^3: 0000 0100 --> 结果为: 0000 0100
2^4: 0000 1000 --> 结果为: 0000 1000
2^5: 0001 0000 --> 结果为: 0000 0000 此处 `与操作` 结果为 0,说明未完成
由此可以得到结论: 第五步没有完成
用 javascript 实现如下
/**
* description:根据 二进制转换成的 10 进制,经过对比得到下一个未完成的步骤
* @param {Number} stepBinaryToTenHex 二进制转换的10进制值
* @param {Number} maxStep 最大可记录步骤数,默认为 8
* */
function calcNextStep(stepBinaryToTenHex, maxStep = 8) {
// 默认步数为第 1 步
let power = 1
for (let step = 1; step <= maxStep; step++) {
if ((stepBinaryToTenHex & power) === 0) {
// 若 `与操作` 结果为 0
// 说明当次步骤还未完成,返回该步骤
return step
}
// 若 `与操作` 结果不为 0,说明是已完成
// 继续增大 2 的幂次方
power *= 2
}
}
calcNextStep(15) // 5
都读到最后了、留下个建议如何