JavaScript中的32位带符号乘法和64位结果

dra*_*oot 1 javascript algorithm integer multiplication

我正在用JavaScript开发VM,需要将两个有符号的32位数字与一个以64位有符号结果存储为两个32位有符号数字(高32位和低32位)相乘。

我设法通过将两个数字都分成16位对并乘以它们来对无符号数字执行相同的操作a*b = (ah * 2^16 + al) * (bh * 2^16 + bl)

function mul_32_unsigned( a, b )
{
  var ah = a >>> 16;
  var bh = b >>> 16;
  var al = a & 0xFFFF;
  var bl = b & 0xFFFF;

  var mid = ah * bl + al * bh;
  var albl = al * bl;

  var imm = mid + ( albl >>> 16 );

  var carry = ( imm > 0xffffffff ) ? 0x10000 : 0;

  var lo = ( ( mid << 16 ) + albl ) >>> 0;
  var hi = ( ah * bh + ( imm >>> 16 ) + carry ) >>> 0;

  return [ lo, hi ];
}
Run Code Online (Sandbox Code Playgroud)

但是,我不太了解如何对带符号的数字执行相同的操作。我唯一能想到的就是否定任何负数ab使两者均为正数,执行无符号乘法,然后在需要时取反结果,但这感觉像是一个无知的次优解决方案。关于如何做得更好的任何想法?拆分ab为两个16位有符号数每个似乎是合乎逻辑的,但后来我觉得失去了对如何在不任何错误进行休息。

ps如果您也认为我的未签名实现也不理想,请也指出这一点。

hob*_*bbs 5

将带符号的32位整数拆分为两个16位整数的正确方法是带符号的16位上半部分和带符号的16位下半部分-您需要对负数进行调整,方法是减去一个从上半部分开始,并在下半部分加上2 ^ 16(以使其为正数)。

例如,数字-100000应该变成-2的上半部分和31072的下半部分。通过重构-2 * 2 ^ 16 + 31072 == -131072 + 31072 == -100000可以看到。

之后,您可以照常执行交叉乘法算法;结果的上半部分将是一个有符号的32位整数(因为它是其中一些有符号的乘积之和),而下半部分将是一个无符号的32位整数。解释它涉及反向执行相同的“技巧”。

顺便说一句,这相当于对如果您在本地进行乘法的机器上查看本地整数的各个单词所看到的内容的自然解释。