简体   繁体   English

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

[英]Why would I use Math.imul()?

Does it perform better than * expressions? 它的表现比*表达式好吗? Why? 为什么?

This article describes it as being useful for projects like Emscripten. 本文将其描述为对Emscripten等项目有用。 Why is that? 这是为什么?

Thanks 谢谢

Short version 精简版

Math.imul(a,b) multiplies a and b as though they were 32 bit signed integers. Math.imul(a,b)将a和b相乘,就像它们是32位有符号整数一样。 (a*b)|0 does the same, but may give incorrect results for large numbers. (a*b)|0作用相同,但可能会给大数字带来错误的结果。

Long version 长版

You would use Math.imul whenever you want to multiply two numbers, and you want the multiplication to act as though the two numbers were 32 bit signed integers. 每当你想要乘以两个数字时,你就会使用Math.imul ,并且你希望乘法就像两个数字是32位有符号整数一样。 That is, you want integer multiplication modulo 2^32. 也就是说,你想要整数乘法模2 ^ 32。

Normally, you can get this effect by using a bitwise operator on the result. 通常,您可以通过对结果使用按位运算符来获得此效果。 For instance, (0xffffffff + 1)|0 quite correctly gives you 0 . 例如, (0xffffffff + 1)|0非常正确地给出0 However, this doesn't work for multiplication. 但是,这不适用于乘法。 (0x7fffffff * 0x7fffffff)|0 gives us 0 , when 32 bit multiplication of the two numbers would give us 1 . (0x7fffffff * 0x7fffffff)|0给出0 ,当(0x7fffffff * 0x7fffffff)|0 32位乘法给出1 The reason for this failure is precision. 这种失败的原因是精确性。 The Number type is a IEEE754 double precision floating point number, which has 53 bits of mantissa. Number类型是IEEE754双精度浮点数,它有53位尾数。 When you try to use numbers larger than 2^53, you start losing precision. 当您尝试使用大于2 ^ 53的数字时,您开始失去精度。 You can test this by running Math.pow(2,53) == Math.pow(2,53)+1 in your browser. 您可以在浏览器中运行Math.pow(2,53) == Math.pow(2,53)+1来测试。

When you multiply two 32 bit numbers in Javascript and truncate the result using a bitwise operator the intermediate result may be larger than 2^53 and may thus be incorrect, which means that the end result of course will also be incorrect. 当您在Javascript中将两个32位数相乘并使用按位运算符截断结果时,中间结果可能大于2 ^ 53,因此可能不正确,这意味着最终结果当然也将是不正确的。

I just did a quick benchmark in Chrome, on a Windows 10 computer. 我刚刚在Windows 10计算机上对Chrome进行了快速基准测试。

First, I ran this code a bunch of times : 首先,我多次运行此代码:

var result;
for(var i = 0; i < 100000000; i++) {
    result = 2 * 4;
}

(see also this Fiddle ) (另见小提琴

Then, I ran this code a bunch of times : 然后,我多次运行此代码:

var result;
for(var i = 0; i < 100000000; i++) {
    result = Math.imul(2, 4);
}

(see also this Fiddle ) (另见小提琴

In both cases, execution time averages around 60ms. 在这两种情况下,执行时间平均约为60ms。 So, at least in Chrome, there's no performance gained or lost from using just Math.imul() . 所以,至少在Chrome中,使用Math.imul()并没有获得或失去任何性能。

So why use it? 那么为什么要用呢? Well, there's probably few to no use cases where you'll ever want to use it in handwritten JavaScript. 好吧,可能很少甚至没有用于手写JavaScript的用例。 You will, however, see it a lot in asm.js code that's generated by emscripten . 但是,您将在emscripten生成的asm.js代码中看到很多内容

Asm.js is a very strict subset of JavaScript that's practically impossible to handcode by any human developer, but that can be generated relatively easily when compiling from C/C++ to JavaScript. Asm.js是一个非常严格的JavaScript子集,几乎不可能被任何人类开发人员手动编码,但是从C / C ++编译到JavaScript时可以相对容易地生成。 Asm.js code is much closer to machine code than ordinary JavaScript code, which allowed browsers to heavily optimise for any code written in asm.js. Asm.js代码比普通的JavaScript代码更接近机器代码,这使得浏览器可以对asm.js中编写的任何代码进行大量优化。 In browsers that implemented those optimizations, your code will typically run about 50% of the speed of a C/C++ program that is compiled to machine code. 在实现这些优化的浏览器中,您的代码通常将运行编译为机器代码的C / C ++程序速度的大约50%。 That may seem slow, but it's a hell of a lot faster than any ordinary JavaScript. 这可能看起来很慢,但它比任何普通的JavaScript都要快得多。

Anyway, what I'm saying, is that there is literally no reason to use Math.imul() in your handwritten code unless, perhaps, if you're a C/C++ programmer still trying to get used to JavaScript. 无论如何,我所说的是,实际上没有理由在你的手写代码中使用Math.imul() ,除非你是一个C / C ++程序员,但仍然习惯于习惯JavaScript。 Using Math.imul() really has no benefits, except when you're writing asm.js code, and that's something you're not supposed to do as a human developer in the first place, because asm.js is both very hard to read and has very strict syntax rules! 使用Math.imul()确实没有任何好处,除非你在编写asm.js代码,并且这首先是你不应该做的人类开发人员,因为asm.js很难阅读并具有非常严格的语法规则!

For more info on asm.js, see eg. 有关asm.js的更多信息,请参阅eg。 John Resig's article from 2013 or the official specs . John Resig的文章来自2013年官方规格

I think it performs better because it's more low level, its implementation may go "down to the metal". 我认为它表现得更好,因为它的级别更低,它的实现可能会“降到金属”。 With the 32-bit restriction the multiplication could be done directly with the processor with less intermediate abstractions/conversions. 使用32位限制,可以直接使用具有较少中间抽象/转换的处理器来进行乘法。

Cheers 干杯

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM