为了账号安全,请及时绑定邮箱和手机立即绑定

如何用八(8)个4位整数创建一个32位整数?

如何用八(8)个4位整数创建一个32位整数?

喵喔喔 2021-03-31 11:51:29
假设我有一个最大的32位整数-const a =  ((2 ** 32) - 1)  const b =  parseInt("11111111111111111111111111111111", 2) // 32 bits, each is a one!  console.log(a === b) // trueconsole.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 bitsprint(make([ 15 ])) // 1111// 8 bitsprint(make([ 15, 15 ])) // 11111111// 12 bitsprint(make([ 15, 15, 15 ])) // 111111111111// 16 bitsprint(make([ 15, 15, 15, 15 ])) // 1111111111111111// 20 bitsprint(make([ 15, 15, 15, 15, 15 ])) // 11111111111111111111// 24 bitsprint(make([ 15, 15, 15, 15, 15, 15 ])) // 111111111111111111111111// 28 bitsprint(make([ 15, 15, 15, 15, 15, 15, 15 ])) // 1111111111111111111111111111// almost there ... now 32 bitsprint(make([ 15, 15, 15, 15, 15, 15, 15, 15 ])) // -1 :(我得到了,-1但预期的结果是所有的32位或11111111111111111111111111111111。更糟糕的是,如果我从预期的结果开始并往回走,我会得到预期的结果-const c = `11111111111111111111111111111111`const d =   parseInt(c, 2)  console.log(d) // 4294967295console.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)) // 11111111const c =  b | (a << 8)  console.log(c.toString(2)) // 111111111111是什么赋予了?目标是使用JavaScript将八(8)个4位整数转换为单个32位整数-这只是我的尝试。我很好奇我的功能在哪里中断,但是我对其他解决方案持开放态度。我想避免将每个4位整数转换为二进制字符串,将二进制字符串混在一起,然后将二进制字符串解析为单个int。数值解决方案是首选。
查看完整描述

1 回答

?
德玛西亚99

TA贡献1770条经验 获得超3个赞


按位运算符将产生一个带符号的32位数字,这意味着,如果位置31处的位(从右边的最低有效位(即位0)开始计数)为1,则该数字将为负数。


为避免这种情况的发生,请使用<<或以外的其他运算符|,这两个运算符均会导致生成带符号的32位数字。例如:


(bit * 2**e) + make (more, e + 4)

强制无符号32位

移位运算符旨在将结果强制进入有符号的32位范围,至少在mdn上要求(在撰写本文时):


所有按位运算符的操作数都将转换为有符号的32位整数


实际上,这并非完全正确。该>>>运营商是一个例外。EcmaScript 2015的12.5.8.1节指出,操作数在移入0位之前已映射到32位无符号。因此,即使您将零位移位,也会看到这种效果。


您只需将其应用于最终值一次,例如在您的print函数中:


console.log((n>>>0).toString(2))

BigInt解决方案

如果您甚至需要超过32位,并且您的JavaScript引擎像某些已经支持的那样支持BigInt,则将BigInts用于按位运算符所涉及的操作数-这样,它们将不使用32位带符号数字换行(请注意后缀) :n


const make = ([ bit, ...more ], e = 0n) =>

  bit === undefined

    ? 0n

    : (bit << e) + make (more, e + 4n)


const print = n =>

  console.log(n.toString(2))


// Test

for (let i=1; i<20; i++) {

    print(make(Array(i).fill(15n))) // longer and longer array...

}

注意:如果在执行上述操作时遇到错误,请使用Chrome重试...


查看完整回答
反对 回复 2021-04-08
  • 1 回答
  • 0 关注
  • 226 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号