我为什么要使用Math.imul()?

时间:2014-01-10 19:29:27

标签: javascript math

它的表现是否优于*表达式?为什么呢?

This article将其描述为对Emscripten等项目有用。那是为什么?

由于

3 个答案:

答案 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 2013official specs

答案 2 :(得分:-3)

我认为它表现更好,因为它的级别更低,它的实现可能会“降到金属”。使用32位限制,可以直接使用具有较少中间抽象/转换的处理器进行乘法。

干杯