Strange Result for Math.pow() in JavaScript across

2019-05-27 03:11发布

问题:

Maybe this only happens in chrome latest version.

Some weird behavior for the negative exponent value only in the Chrome browser.

I already checked with different browsers & find it really weird. As FireFox & Chromium will show the exact same result while Chrome latest version will show the different result for some of the examples. And I don't know what's going on?

Here are my findings for different browsers...

FireFox

Chromium

Chrome

Weird Thing!!

For the Math.pow(10,-4) and Math.pow(10,-5), the answer should be 0.0001 and 0.00001 respectively but why chrome's latest version shows0.00009999999999999999 and 0.000009999999999999999 respectively!!

Can anyone have an explanation for the above scenario that why chrome is doing like this?

FYI - All browser's version already mentioned in images.

回答1:

Returns an implementation-dependent approximation of the result of raising base to the power exponent.

https://tc39.github.io/ecma262/#sec-applying-the-exp-operator

0.0001 is the next representable number above 0.00009999999999999999. (The results differ by one unit of least precision.)

This appears to have changed in 74.0.3700.0 (changelog), corresponding to a V8 roll to 7.4.113, including this commit:

https://chromium.googlesource.com/v8/v8/+/98453126c109016c9d32c6ebd89dd83f69dd8efb

[builtins] [turbofan] Refactor Float64Pow to use single implementation

Remove platform-specific Float64Pow implementations and utils Pow in favor of a base::ieee754::pow implementation.

This unifies the implementation of pow for the compiler, wasm, and runtime.

So they switched the implementation of Pow to something else.

To demonstrate that we're getting a different number and it's not related to the float-to-decimal conversion:

> 10**-4 == 1e-4

Or, if you're not convinced and want to explore floats at a low level, dump the number as hex:

(Requires Firefox 67.)

from_bits = b => new Float64Array(new BigUint64Array([b]).buffer)[0]
to_bits = f => new BigUint64Array(new Float64Array([f]).buffer)[0]

console.log(to_bits(Math.pow(10,-4)).toString(16))

I get 3f1a36e2eb1c432d in Firefox and 3f1a36e2eb1c432c in Chrome.