Converting a number from a decimal in a string to binary floating-point is an operation, and it does produce “precision errors.” If the source number is not representable in the destination format, it is rounded.
In the examples you show, every operation has a rounding error, except for converting the source text 100
to the number 100.
In console.log(4.015)
, the decimal numeral “4.015” represents the number 4.015. When this is converted to the IEEE-754 64-bit binary floating-point that JavaScript uses, the result is 4.01499999999999968025576890795491635799407958984375. (That has lots of digits, but it is actually represented internally in a form equivalent to 4520488125973135 times 2−50.) Then, to print this to the console, it is converted from binary floating-point to decimal. When doing the conversion, JavaScript uses just enough decimal digits to uniquely distinguish the value from neighboring values that are representable in binary floating-point. The result is the string “4.015”. So the binary floating-point value has been rounded to a different decimal value—producing the same string as the original. So, in console.log(4.015)
, there are actually two conversion operations, there is rounding error in both of them, and the behavior of the software acts to conceal the rounding errors.
In console.log(parseFloat("4.015"))
, the same thing happens, except the first conversion is done when parseFloat
is called instead of when 4.015
is interpreted in the source code.
In console.log(4.015 * 100)
, there are four operations and three rounding errors:
4.015
is converted to binary floating-point, which has the rounding error described above.
100
is converted to binary floating-point, and there is no rounding error because 100 is representable in binary floating-point.
- The two binary floating-point numbers are multiplied, and there is a rounding error, producing 401.49999999999994315658113919198513031005859375.
- That result is converted to a decimal string. The result is “401.49999999999994” because we need that many digits to distinguish it from the two neighboring representable values, 401.4999999999998863131622783839702606201171875 and 401.5.
In summary:
- Every operation, including conversions between binary and decimal, may be subject to rounding error.
- The default JavaScript formatting acts to conceal some rounding errors; round trips from decimal numerals shorter than 16 digits will always produce the original number (within the finite range of the format).