【发布时间】:2019-08-18 20:01:02
【问题描述】:
假设我有一个最大 32 位整数 -
const a =
((2 ** 32) - 1)
const b =
parseInt("11111111111111111111111111111111", 2) // 32 bits, each is a one!
console.log(a === b) // true
console.log(a.toString(2))
// 11111111111111111111111111111111 (32 ones)
console.log(b.toString(2))
// 11111111111111111111111111111111 (32 ones)
到目前为止一切顺利。但现在假设我想使用八 (8) 个 4 位数字制作一个 32 位数字。这个想法很简单:将每个 4 位序列移位 (<<) 到适当的位置,然后将它们相加 (+) -
const make = ([ bit, ...more ], e = 0) =>
bit === undefined
? 0
: (bit << e) + make (more, e + 4)
const print = n =>
console.log(n.toString(2))
// 4 bits
print(make([ 15 ])) // 1111
// 8 bits
print(make([ 15, 15 ])) // 11111111
// 12 bits
print(make([ 15, 15, 15 ])) // 111111111111
// 16 bits
print(make([ 15, 15, 15, 15 ])) // 1111111111111111
// 20 bits
print(make([ 15, 15, 15, 15, 15 ])) // 11111111111111111111
// 24 bits
print(make([ 15, 15, 15, 15, 15, 15 ])) // 111111111111111111111111
// 28 bits
print(make([ 15, 15, 15, 15, 15, 15, 15 ])) // 1111111111111111111111111111
// almost there ... now 32 bits
print(make([ 15, 15, 15, 15, 15, 15, 15, 15 ])) // -1 :(
我得到-1,但预期结果是全32位,或11111111111111111111111111111111。
更糟糕的是,如果我从预期的结果开始并向后工作,我会得到预期的结果 -
const c =
`11111111111111111111111111111111`
const d =
parseInt(c, 2)
console.log(d) // 4294967295
console.log(d.toString(2) === c) // true
我尝试调试我的 make 函数以确保没有明显的问题 -
const make = ([ bit, ...more ], e = 0) =>
bit === undefined
? `0`
: `(${bit} << ${e}) + ` + make (more, e + 4)
console.log(make([ 15, 15, 15, 15, 15, 15, 15, 15 ]))
// (15 << 0) + (15 << 4) + (15 << 8) + (15 << 12) + (15 << 16) + (15 << 20) + (15 << 24) + (15 << 28) + 0
该公式看起来像是检查出来的。我想这可能与+ 有关并切换到按位或 (|) 应该在这里有效地做同样的事情-
const a =
parseInt("1111",2)
const b =
(a << 0) | (a << 4)
console.log(b.toString(2)) // 11111111
const c =
b | (a << 8)
console.log(c.toString(2)) // 111111111111
但是,当我尝试合并所有八 (8) 个数字时,我的 make 函数遇到了同样的错误 -
const make = ([ bit, ...more ], e = 0) =>
bit === undefined
? 0
: (bit << e) | make (more, e + 4)
const print = n =>
console.log(n.toString(2))
print(make([ 15, 15, 15, 15, 15, 15, 15 ])) // 1111111111111111111111111111 (28 bits)
print(make([ 15, 15, 15, 15, 15, 15, 15, 15 ])) // -1 :(
什么给了?
目标是使用 JavaScript 将八 (8) 个 4 位整数转换为一个 32 位整数 - 这只是我的尝试。我很好奇我的功能哪里出了问题,但我愿意接受其他解决方案。
我想避免将每个 4 位整数转换为二进制字符串,将二进制字符串混合在一起,然后将二进制字符串解析为单个 int。首选数值解。
【问题讨论】:
-
看起来 bitwise operators 说 “数字
-2147483648和2147483647是可以通过 32 位有符号数字表示的最小和最大整数。” 确实(15 << 28)超出了这个范围,但是 JavaScript 的 MAX_SAFE_INTEGER 最多支持 53 位。是否有一种安全可靠的方法可以对大于 32 位的数字使用位运算符? -
签名真的不能接受吗?毕竟它们是相同的位,只是解释略有不同
标签: javascript twos-complement base-conversion