How does the V8 toString(radix) method in Google Chrome or in Node.js handle floating point numbers?

Issue

The method works clearly with integer numbers, e.g.

``````(25).toString(2)
= '11001'

(25).toString(16)
= '19'

(25).toString(36)
= 'p'
``````

But entering floats results in

``````(0.1).toString(2)
= '0.0001100110011001100110011001100110011001100110011001101'

(0.1).toString(16)
= '0.1999999999999a'

(0.1).toString(36)
= '0.3lllllllllm'
``````

V8 is said to be an open-source engine. However, I cannot find the exact implementation of this method in the repository in order to understand it. How does the function handle floats?

Solution

(V8 developer here.)

@pilchard’s link is right; more specifically the function you’re looking for is DoubleToRadixCString.

The observation that 0.1 (decimal) is a non-terminating fraction in its binary representation (which is, of course, how doubles are stored inside computers) is a nice illustration of the underlying reason why `0.1 * 3 == 0.30000000000000004`: the non-terminating fractions are necessarily cut off at some point, which constitutes a rounding error, and some operations make these rounding errors visible. It’s the binary equivalent of a similar effect in decimal: when you represent 1/3 as "0.333333" (arbitrarily choosing 6 digits as the represented length, but if you only cut off after 100 digits that wouldn’t really change anything), and multiply that by 3, you get "0.999999", not 1.