可以在位掩码中安全使用的 Javascript 的最大值是多少?
What is the Javascript's highest value that can be safely used in a bitmask?
假设我想在 Javascript 中创建一个位掩码。我会像这样切换一下:
mask |= (1 << bit);
清除有点像这样:
mask &= ~(1 << bit);
并检查是否设置了这样的位:
(bit & mask) != 0
我的问题是,它在 Javascript 中工作的最安全位数是多少?我主要有三个猜测:
- 32 位,因为超过 32 位的位操作可能未定义
- 53 位,因为
Number.MAX_SAFE_INTEGER
是 2^53 - 1
- 64 位,因为 Javascript 每个数字使用 64 位
哪个是正确的?还是其他原因?
Bitwise operators treat their operands as a set of 32 bits (zeros and ones) and return standard JavaScript numerical values.
6.1.6.1.9 Number::leftShift ( x, y )
- Let lnum be ! ToInt32(x).
- Let rnum be ! ToUint32(y).
- Let shiftCount be the result of masking out all but the least significant 5 bits of rnum, that is, compute rnum & 0x1F.
- Return the result of left shifting lnum by shiftCount bits. The result is a signed 32-bit integer.
请注意,如果使用 BigInt 对象,则位掩码仅受内存限制,因此可以管理超过 32 位的掩码。通常按照问题的思路,例如,可以将 127 位的掩码设置为全 1,如下所示...
x = ( 1n << 128n ) - 1n
- x: 340282366920938463463374607431768211455n
- x.toString(2):111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111ME
...然后,比如说,清除第 16 位...
x &= ~( 1n << 16n )
- x: 340282366920938463463374607431768145919n
- x.toString(2):11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111往
...并检查是否设置了位,比如 17...
( ( 1n << 17n ) & x ) !== 0n
- 正确
...或检查第 16 位是否已设置...
( ( 1n << 16n ) & x ) !== 0n
- 错误
JavaScript 也有 BigUint64Array 对象,它是平台字节顺序的 64 位无符号 BigInt 整数类型化数组。这也是 33 位到 64 位范围内位掩码要求的选项...
请注意,对于极端 BigInt 掩码,将 Uint32 数组作为集体位掩码进行管理可能比使用本机 BigInt 位操作函数更高效。因此,如果性能有问题,则需要进行实验以确定 BigInt 位掩码是否适合手头的用例...
假设我想在 Javascript 中创建一个位掩码。我会像这样切换一下:
mask |= (1 << bit);
清除有点像这样:
mask &= ~(1 << bit);
并检查是否设置了这样的位:
(bit & mask) != 0
我的问题是,它在 Javascript 中工作的最安全位数是多少?我主要有三个猜测:
- 32 位,因为超过 32 位的位操作可能未定义
- 53 位,因为
Number.MAX_SAFE_INTEGER
是2^53 - 1
- 64 位,因为 Javascript 每个数字使用 64 位
哪个是正确的?还是其他原因?
Bitwise operators treat their operands as a set of 32 bits (zeros and ones) and return standard JavaScript numerical values.
6.1.6.1.9 Number::leftShift ( x, y )
- Let lnum be ! ToInt32(x).
- Let rnum be ! ToUint32(y).
- Let shiftCount be the result of masking out all but the least significant 5 bits of rnum, that is, compute rnum & 0x1F.
- Return the result of left shifting lnum by shiftCount bits. The result is a signed 32-bit integer.
请注意,如果使用 BigInt 对象,则位掩码仅受内存限制,因此可以管理超过 32 位的掩码。通常按照问题的思路,例如,可以将 127 位的掩码设置为全 1,如下所示...
x = ( 1n << 128n ) - 1n
- x: 340282366920938463463374607431768211455n
- x.toString(2):111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111ME
...然后,比如说,清除第 16 位...
x &= ~( 1n << 16n )
- x: 340282366920938463463374607431768145919n
- x.toString(2):11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111往
...并检查是否设置了位,比如 17...
( ( 1n << 17n ) & x ) !== 0n
- 正确
...或检查第 16 位是否已设置...
( ( 1n << 16n ) & x ) !== 0n
- 错误
JavaScript 也有 BigUint64Array 对象,它是平台字节顺序的 64 位无符号 BigInt 整数类型化数组。这也是 33 位到 64 位范围内位掩码要求的选项...
请注意,对于极端 BigInt 掩码,将 Uint32 数组作为集体位掩码进行管理可能比使用本机 BigInt 位操作函数更高效。因此,如果性能有问题,则需要进行实验以确定 BigInt 位掩码是否适合手头的用例...