Question- Since integers above 2^53 can't be accurately represented in doubles, how does JS decide on their decimal representation when they are printed as strings?
1. Way of Printing decimal numbers in JS
JavaScript numbers are internally stored in binary floating point and usually displayed in the decimal system.
There are two decimal notations used by JavaScript:
Fixed notation
[ "+" | "-" ] digit+ [ "." digit+ ]
Exponential notation
[ "+" | "-" ] digit [ "." digit+ ] "e" [ "+" | "-" ] digit+
An example of exponential notation is 1.2345678901234568e+21
.
Rules for Displaying decimal numbers:
A. Use exponential notation if there are more than 21 digits before the decimal point.
B. Use exponential notation if the number starts with “0.” followed by more than five zeros.
Here is a details of Sect. 9.8.1 of the ECMAScript 5.1 specification describes the algorithm for displaying a decimal number
Given a number
mantissa × 10^pointPos−digitCount
The mantissa of a floating point number is an integer – the significant digits plus a sign. Leading and trailing zeros are discarded. Examples:
The mantissa of 12.34 is 1234.
Case-1. No decimal point: digitCount ≤ pointPos ≤ 21
Print the digits (without leading zeros), followed by pointPos−digitCount zeros.
Case-2. Decimal point inside the mantissa: 0 < pointPos ≤ 21, pointPos < digitCount
Display the pointPos first digits of the mantissa, a point and then the remaining digitCount−pointPos digits.
Case-3. Decimal point comes before the mantissa: −6 < pointPos ≤ 0
Display a 0 followed by a point, −pointPos zeros and the mantissa.
Case-4. Exponential notation: pointPos ≤ -6 or pointPos > 21
Display the first digit of the mantissa. If there are more digits then display a point and the remaining digits. Next, display the character e and a plus or minus sign (depending on the sign of pointPos−1), followed by the absolute value of pointPos−1. Therefore, the result looks as follows.
mantissa0 [ "." mantissa1..digitCount ]
"e" signChar(pointPos−1) abs(pointPos−1)
Question-
However, in Javascript, we get 36028797018963970 instead. It seems to try to round numbers to get a 0 at the end, but not always - for instance, 2^55-4 is represented correctly with 4 at the end.
Is there some place in the spec that defines this weird behavior?
Check: How numbers are encoded in JavaScript specially ==>5. The maximum integer
Additional Reference: https://medium.com/dailyjs/javascripts-number-type-8d59199db1b6