TL;DR: No.

As you point out, JavaScript dictates that all numbers be 64-bit doubles.
So V8 always behaves as if all numbers were stored as 64-bit doubles. (When
it doesn't, that's a bug.)

Due to 64-bit floats having 52 bit mantissas, any integer up to 2^52 can be
represented exactly. In your example, ts1 and ts2 both fall into this
category. Accordingly, the result of "ts1 - ts2" will also be a perfectly
accurate integer. ts3, however, has more significant digits in its textual
representation than a 64-bit double can represent, so some digits will be
cut off no matter what.

Due to the way floating-point numbers work, adding 438877949516
+ 10.472319812098124124462 will indeed cut off more digits in the result
than adding 16 + 10.472319812098124124462 will. However this has nothing to
do with V8. Java or C++ or any other language using IEEE754 doubles will
behave in the same way.

Rule of thumb: the first ~15 ≈ log10(2^52) non-zero digits of the decimal
representation can be stored, the rest is cut off. So numbers that can be
represented exactly include e.g. 12345678901234500000 and 123456789012345
and 12345678901234.5 and 12345.6789012345 and 0.0000123456789012345 etc.
A caveat is that choosing decimal vs. binary representation affects which
fractions can be represented with a finite number of digits; a common
example is 1/10 which is perfectly represented as "0.1" in decimal, but
cannot be represented exactly in any finite-precision binary number, much
like there is no finite-precision decimal representation of 1/3 =
0.33333... .

For *performance* reasons, V8 internally stores small integers as actual
integers. But from a functional point of view (i.e. what results you get
from any given arithmetic operation), this internal detail should never be
observable.


On Tue, Mar 8, 2016 at 8:05 PM, 'Charlie Andrews' via v8-users <
v8-users@googlegroups.com> wrote:

> *TL;DR*
> A friend mentioned that v8 might have accuracy optimizations built in for
> integer arithmetic. Is this true?
>
> *Long version:*
> With:
>
> var ts1 = 438877949516;
> var ts2 = 438877949500;
> var ts3 = 10.472319812098124124462;
>
> does
>
> (ts1 - ts2) + ts3
>
> produce a result that's accurate to more digits than:
>
> (ts1 + ts3) - ts2
>
> *The reasoning for why it might not be more accurate*
> Supposedly, all Javascript numbers are stored as 64 bit floating point
> numbers. 64 bit floats are generally stored according to IEEE 754-1985
> <https://en.wikipedia.org/wiki/IEEE_754-1985>, which means they're broken
> up into 3 fields: a 1 bit sign, an 11 bit exponent, and a 52 bit
> significand. This means that the number 438877949516 is actually stored
> as
>
>              sign  exponent     significand
> Binary       0     00000100101
>  1.1001100010111100101010000011100100110000000000000000
> Decimal      0           38           1.5966286792390747
>
> You can get back to the original number with:
>
> +1 * 1.5966286792390747 * 2^38 ≈ 438877949516
>
> (Note: this ignores bias in the exponent, which doesn't really matter for
> example purposes)
>
> A fixed number of bits in the significand (52) essentially means that you
> have a fixed number of binary significant figures. You can represent really
> really big numbers, but that means that you lose fractional accuracy. How
> many fractional binary significant figures you can provide is given by 52 -
> floor(log2(N)). In the case of 438877949516, this means that we dedicate 38
> bits to representing the scale of the number and we can only dedicate 14
> bits to fractional accuracy, so the smallest difference between two numbers
> as big as 438877949516 is 1/(2^14), or .00006104.
>
> This means that ts1 - ts2 (i.e. 438877949516 - 438877949500) gives us a
> number that's within .00006104 of 16. Add ts3 (10.472319812098124124462),
> and our significant figure rules tell us that we still only have a number
> within .00006104 of the true answer.
>
> *The reasoning for why it might be more accurate*
> If v8 has some optimization to do integer math exactly, then the story
> changes. ts1 - ts2 (i.e. 438877949516 - 438877949500) now gives us an
> exact answer of 16 with infinite fractional accuracy. We then add ts3 
> (10.472319812098124124462)
> and, because numbers around 10 have a fractional resolution of 1/2^(52 -
> floor(log2(10)) - about 1.7763568e-15 - we have a number that's about 10
> orders of magnitude more accurate.
>
> Woo! Sorry for the long explanation, but this is complicated stuff.
> Insight is very much appreciated :)
>
> --
>
> Charlie Andrews |  Software Engineer |  charl...@google.com
>
>
> --
> --
> v8-users mailing list
> v8-users@googlegroups.com
> http://groups.google.com/group/v8-users
> ---
> You received this message because you are subscribed to the Google Groups
> "v8-users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to v8-users+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
-- 
v8-users mailing list
v8-users@googlegroups.com
http://groups.google.com/group/v8-users
--- 
You received this message because you are subscribed to the Google Groups 
"v8-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to v8-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to