2

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

enter image description here

Chromium

enter image description here

Chrome

enter image description here

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.

bud-e
  • 1,511
  • 1
  • 20
  • 31
  • 2
    What's different here isn't `Math.pow` (it's standardized and does give the same result) but `Number.toString`. EcmaScript doesn't specify a precise algorithm for this conversion. – Denys Séguret May 02 '19 at 19:08
  • Possible duplicate of [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) – Thomas May 07 '19 at 09:44
  • [Floating-Point Questions Are Endless on stackoverflow.com](https://www.exploringbinary.com/floating-point-questions-are-endless-on-stackoverflow-com/) – Thomas May 07 '19 at 09:45

1 Answers1

3

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.

Community
  • 1
  • 1
Josh Lee
  • 171,072
  • 38
  • 269
  • 275
  • 1
    @JohnColeman It's close enough. It's enough decimal places to uniquely determine a specific 64-bit float as opposed to some other number. Try the commentary at https://doc.rust-lang.org/src/core/num/flt2dec/mod.rs.html – Josh Lee May 03 '19 at 12:41
  • The fraction on the smallest positive 64-bit float has 751 digits when written in base 10, but we usually write 5e-324 out of convenience, since these numbers are usually used as approximations to what we actually meant. – Josh Lee May 03 '19 at 12:46