Search code examples
javascriptfloating-pointroundingrounding-error

Why are e notation numbers evaluated differently in JavaScript?


I've been investigating some rounding oddities in JavaScript stemming from their floating point implementation:

> Number(Math.round(1.005*100)/100);
1

I understand this is rounded down because the floating point representation of (1.005 * 100) is 100.49999999999999

But when I do this:

> Number(Math.round(1.005e2)+'e-2');
1.01

or more succinctly:

>1.005e2;
100.5

I get the expected (unexpected!) result. Why does JavaScript evaluate (1.005e2) as 100.5? Is it using another primitive type behind the scenes or is this a result of string parsing?

If anyone can point me to a spec about e notation implementation, I would be grateful!


Solution

  • I guess you were expecting that by specifying xe2, it would perform x * 100 internally somehow?

    The spec does not specify the exact process of how number literals should be evaluated, only what the result should be:

    The MV of DecimalLiteral :: DecimalIntegerLiteral ExponentPart is the MV of DecimalIntegerLiteral × 10e, where e is the MV of ExponentPart.

    (Note: "MV" means mathematical value)

    Later it says:

    Once the exact MV for a numeric literal has been determined, it is then rounded to a value of the Number type.

    This seems to indicate that any intermediate MVs don't have to be valid Number values and that the engine can use any representation of such values.


    Lets think about it another way:

    100.5 and 1.005e2 are two notations for the same number. Wouldn't it be strange if one of them (1.005e2) would actually result in a different value?

    1.005 * 100 however is an operation on two individual numbers. While you might expect the result to be the same as well, the way you are getting the result is different.