如何使用位掩码在 JavaScript 中存储布尔值
How to use bitmasks to store boolean values in JavaScript
阅读有关如何使用位掩码存储布尔值后,我有点困惑。我想要一组布尔值,然后为这些值的每个组合生成一个唯一的整数。这是目前的系统:
var a = 1 << 1
var b = 1 << 2
var c = 1 << 3
var d = 1 << 4
var uniqueint1 = getInt(true, false, false)
var uniqueint2 = getInt(true, true, false)
var uniqueint3 = getInt(true, true, true)
// ...
function getInt(x, y, z) {
var value = a
if (x) value = value | b
if (y) value = value | c
if (z) value = value | d
return value
}
但问题是,我不确定我是否应该按照以下方式处理 "not" 案例:
function getInt(x, y, z) {
var value = a
if (x) value = value | b
else value = value ^ b
if (y) value = value | c
else value = value ^ c
if (z) value = value | d
else value = value ^ z
return value
}
我所知道的是我见过 |
、&
和 ^
与位掩码相关,而且我知道要查找布尔值是否在您执行的位掩码中var yes = value & b
,但我只是对如何生成位掩码以使其同时处理 if (true) 和 if (false) 情况感到困惑。不确定我是否应该在某处使用 ^
,或者我做错了什么。请指教。谢谢!
NOT 运算将反转 该位,因此需要设置它才能被清除。
(假设您想在现有值上打开或关闭位:)您可以将 NOT 与 AND 掩码一起使用来清除位,如下所示:
var v = 0xff; // value
var bit3 = 1<<3; // the bit we want to clear
// clear bit 3:
v &= ~bit3; // create a AND mask inverting bit 3 and AND with value
console.log(v.toString(2));
v &= ~bit3; // will not set the bit even when already cleared
console.log(v.toString(2));
您当然也可以检查该位是否已设置,如果是则不设置:
var v = 0xff;
var bit3 = 1<<3;
if (v & bit3) v ^= bit3; // NOT bit 3 if set
console.log(v.toString(2));
// should not trigger:
if (v & bit3) console.log("Whaa");
要改为设置它,无论状态如何,您都可以使用 OR:
if (v & bit3) v ^= bit3; // NOT bit 3 if set
else {v |= bit3}; // set it not set already
如果您需要一次清除多个位,您可以先将这些位组合在一起,
然后将其与 NOT 一起用于 AND 掩码:
var v = 0xff;
var bit1 = 1<<1;
var bit3 = 1<<3;
// create NOT mask:
var mask = bit1 | bit3;
// clear bits:
v &= ~mask;
console.log(v.toString(2));
所以在函数中你可以这样:
var a = 0xff;
var b = 1 << 2
var c = 1 << 3
var d = 1 << 4
function getInt(x, y, z) {
var value = a;
value = x ? value | b : value & ~b;
value = y ? value | c : value & ~c;
value = z ? value | d : value & ~d;
return value
}
// turn off bit c/d (bit index 3 & 4):
console.log(getInt(true,false,false).toString(2));
// turn on c, off b/d
console.log(getInt(false,true,false).toString(2));
// with same value turn off all, then on c:
a = getInt(false, false, false);
console.log(getInt(false,true,false).toString(2));
通过在开始时执行 var value=1
,您已经将值设置为 2,因为 1<<1=2
。我建议您设置 value=0
并删除 else value = value ^ c
,因为当您从全零开始时该操作不会导致任何更改。您的代码如下所示:
var a = 1 << 1
var b = 1 << 2
var c = 1 << 3
var d = 1 << 4
function getInt(x, y, z) {
var value = 0
if (x) value = value | b
if (y) value = value | c
if (z) value = value | d
return value
}
var uniqueint1 = getInt(true, false, false)
var uniqueint2 = getInt(true, true, false)
var uniqueint3 = getInt(true, true, true)
uniqueint1
这会打印出 4
,而不是 uniqueint1
的 6
。
I am not sure if I am supposed to handle the "not" case
你根本不应该处理它。位掩码的作用是,如果您的标志已设置,则您有一个值为 1
的位,如果没有,则有一个值为 0
的位。鉴于您的值在任何地方都以 0
s 开头(整数 0),您只需在条件为真时设置该位(按 OR 1),否则您无需执行任何操作。
您可以将代码简化为
function getInt(x, y, z) {
return (0b10 // a
| (x << 2) // 0b00100 if x and 0b00000 else
| (y << 3) // 0b01000 if y and 0b00000 else
| (z << 4)); // 0b10000 if z and 0b00000 else
}
阅读有关如何使用位掩码存储布尔值后,我有点困惑。我想要一组布尔值,然后为这些值的每个组合生成一个唯一的整数。这是目前的系统:
var a = 1 << 1
var b = 1 << 2
var c = 1 << 3
var d = 1 << 4
var uniqueint1 = getInt(true, false, false)
var uniqueint2 = getInt(true, true, false)
var uniqueint3 = getInt(true, true, true)
// ...
function getInt(x, y, z) {
var value = a
if (x) value = value | b
if (y) value = value | c
if (z) value = value | d
return value
}
但问题是,我不确定我是否应该按照以下方式处理 "not" 案例:
function getInt(x, y, z) {
var value = a
if (x) value = value | b
else value = value ^ b
if (y) value = value | c
else value = value ^ c
if (z) value = value | d
else value = value ^ z
return value
}
我所知道的是我见过 |
、&
和 ^
与位掩码相关,而且我知道要查找布尔值是否在您执行的位掩码中var yes = value & b
,但我只是对如何生成位掩码以使其同时处理 if (true) 和 if (false) 情况感到困惑。不确定我是否应该在某处使用 ^
,或者我做错了什么。请指教。谢谢!
NOT 运算将反转 该位,因此需要设置它才能被清除。
(假设您想在现有值上打开或关闭位:)您可以将 NOT 与 AND 掩码一起使用来清除位,如下所示:
var v = 0xff; // value
var bit3 = 1<<3; // the bit we want to clear
// clear bit 3:
v &= ~bit3; // create a AND mask inverting bit 3 and AND with value
console.log(v.toString(2));
v &= ~bit3; // will not set the bit even when already cleared
console.log(v.toString(2));
您当然也可以检查该位是否已设置,如果是则不设置:
var v = 0xff;
var bit3 = 1<<3;
if (v & bit3) v ^= bit3; // NOT bit 3 if set
console.log(v.toString(2));
// should not trigger:
if (v & bit3) console.log("Whaa");
要改为设置它,无论状态如何,您都可以使用 OR:
if (v & bit3) v ^= bit3; // NOT bit 3 if set
else {v |= bit3}; // set it not set already
如果您需要一次清除多个位,您可以先将这些位组合在一起, 然后将其与 NOT 一起用于 AND 掩码:
var v = 0xff;
var bit1 = 1<<1;
var bit3 = 1<<3;
// create NOT mask:
var mask = bit1 | bit3;
// clear bits:
v &= ~mask;
console.log(v.toString(2));
所以在函数中你可以这样:
var a = 0xff;
var b = 1 << 2
var c = 1 << 3
var d = 1 << 4
function getInt(x, y, z) {
var value = a;
value = x ? value | b : value & ~b;
value = y ? value | c : value & ~c;
value = z ? value | d : value & ~d;
return value
}
// turn off bit c/d (bit index 3 & 4):
console.log(getInt(true,false,false).toString(2));
// turn on c, off b/d
console.log(getInt(false,true,false).toString(2));
// with same value turn off all, then on c:
a = getInt(false, false, false);
console.log(getInt(false,true,false).toString(2));
通过在开始时执行 var value=1
,您已经将值设置为 2,因为 1<<1=2
。我建议您设置 value=0
并删除 else value = value ^ c
,因为当您从全零开始时该操作不会导致任何更改。您的代码如下所示:
var a = 1 << 1
var b = 1 << 2
var c = 1 << 3
var d = 1 << 4
function getInt(x, y, z) {
var value = 0
if (x) value = value | b
if (y) value = value | c
if (z) value = value | d
return value
}
var uniqueint1 = getInt(true, false, false)
var uniqueint2 = getInt(true, true, false)
var uniqueint3 = getInt(true, true, true)
uniqueint1
这会打印出 4
,而不是 uniqueint1
的 6
。
I am not sure if I am supposed to handle the "not" case
你根本不应该处理它。位掩码的作用是,如果您的标志已设置,则您有一个值为 1
的位,如果没有,则有一个值为 0
的位。鉴于您的值在任何地方都以 0
s 开头(整数 0),您只需在条件为真时设置该位(按 OR 1),否则您无需执行任何操作。
您可以将代码简化为
function getInt(x, y, z) {
return (0b10 // a
| (x << 2) // 0b00100 if x and 0b00000 else
| (y << 3) // 0b01000 if y and 0b00000 else
| (z << 4)); // 0b10000 if z and 0b00000 else
}