答案 0 :(得分:17)
简短版
Math.imul(a,b)
将a和b相乘,就好像它们是32位有符号整数一样。 (a*b)|0
也会这样做,但可能会为大数字提供不正确的结果。
长版
每当你想要乘以两个数字时,你会使用Math.imul
,并且你希望乘法就像两个数字是32位有符号整数一样。也就是说,你想要整数乘法模2 ^ 32。
通常,您可以通过对结果使用按位运算符来获得此效果。例如,(0xffffffff + 1)|0
非常正确地为您提供0
。但是,这不适用于乘法。 (0x7fffffff * 0x7fffffff)|0
给我们0
,当两位数的32位乘法给我们1
时。这种失败的原因是精确性。 Number
类型是IEEE754双精度浮点数,具有53位尾数。当您尝试使用大于2 ^ 53的数字时,您开始失去精度。您可以在浏览器中运行Math.pow(2,53) == Math.pow(2,53)+1
来对此进行测试。
当您在Javascript中将两个32位数相乘并使用按位运算符截断结果时,中间结果可能大于2 ^ 53,因此可能不正确,这意味着最终结果当然也是不正确的。< / p>
答案 1 :(得分:0)
我刚刚在Windows 10计算机上对Chrome进行了快速基准测试。
首先,我多次运行此代码:
var result;
for(var i = 0; i < 100000000; i++) {
result = 2 * 4;
}
(另见this Fiddle)
然后,我多次运行此代码:
var result;
for(var i = 0; i < 100000000; i++) {
result = Math.imul(2, 4);
}
(另见this Fiddle)
在这两种情况下,执行时间平均约为60毫秒。因此,至少在Chrome中,仅使用Math.imul()
没有获得或失去任何性能。
为什么要使用它?好吧,可能很少甚至没有用于手写JavaScript的用例。但是,您会在asm.js生成的emscripten代码中看到很多内容。
Asm.js是一个非常严格的JavaScript子集,几乎不可能被任何人类开发人员手动编码,但是从C / C ++编译到JavaScript时可以相对容易地生成。 Asm.js代码比普通的JavaScript代码更接近机器代码,这使得浏览器可以对asm.js中编写的任何代码进行大量优化。在实现这些优化的浏览器中,您的代码通常将运行编译为机器代码的C / C ++程序速度的大约50%。这可能看起来很慢,但它比任何普通的JavaScript都要快得多。
无论如何,我所说的是,实际上没有理由在你的手写代码中使用Math.imul()
,除非你是一个仍然习惯于习惯JavaScript的C / C ++程序员。使用Math.imul()
确实没有任何好处,除非你在编写asm.js代码,并且这首先是你不应该做的人类开发人员,因为asm.js很难阅读并具有非常严格的语法规则!
有关asm.js的更多信息,请参阅eg。 John Resig's article from 2013或official specs。
答案 2 :(得分:-3)
我认为它表现更好,因为它的级别更低,它的实现可能会“降到金属”。使用32位限制,可以直接使用具有较少中间抽象/转换的处理器进行乘法。
干杯