1

const a = 10;
const b = 0.123456789123456789;

console.log((a + b).toFixed(17));


// 10.12345678912345726

As you can see from example above, .12345678912345 , only this part are shown correctly , as I understand Javascript only consider 15 places precision ( including .). If I will change 10 to 100 , it will be same amount , but I was thinking it should be 17 places precision by MDN doc. What doesn't this phrase exactly mean 17 decimal places of precision ?

If I will show it without .toFixed() method , it will show same 15 precision 10.123456789123457 - response of a + b

Url: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number

0stone0
  • 34,288
  • 4
  • 39
  • 64
Andrey Radkevich
  • 3,012
  • 5
  • 25
  • 57
  • 1
    What do you mean by "correctly"? It's not clear to me what you're asking. – deceze Apr 15 '22 at 11:32
  • All this depends above all on the way in which the numerical values are implemented in the systems. Javascript is not intended to be used to make precision calculations, the integer values are limited to that of a processor register, and the floating values are represented in precision and approximation in an exponential representation – Mister Jojo Apr 15 '22 at 11:34
  • 726 - goes after number 5 in response , but it should be 6789 - as I understand js have some limitation for numbers which can be shown after . , but how much numbers is it consider ? I was thinking 17 ( by doc ) , but seems I get it wrong @deceze – Andrey Radkevich Apr 15 '22 at 11:35
  • You're aware of https://stackoverflow.com/q/588004/476…? Do you need to dig into any more detail? – deceze Apr 15 '22 at 11:36
  • These are some good explanation for this problem https://0.30000000000000004.com/ and https://docs.python.org/release/2.5.1/tut/node16.html – PR7 Apr 15 '22 at 12:23

1 Answers1

2

According to JS/ECMAScript specification, the Number type uses double-precision floating point which has 64-bit format (binary64), consists of a sign bit (determines positive or negative value), 11 exponent bits and 52 fraction bits (each digit represents 4-bits, hence 64-bit has 16 digits):

The Number type representing the double-precision 64-bit format IEEE 754-2008 values as specified in the IEEE Standard for Binary Floating-Point Arithmetic.

The maximum positive number which can be represented properly using double precision is 9007199254740992, which can be achieved by using Math.pow(2, 53). If the number range is between Math.pow(2, 53) and Math.pow(2, 54) (or between Math.pow(2, -53) and Math.pow(2, -54)), only even numbers can be represented properly because the exponent bits will affect LSB (least-significant bit) on the fraction bits.

Let's review the large number part:

var x = 12345678912345.6789

var x = new Number(12345678912345.6789)

This number contains more than 52 fractional bits (72 bits in total), hence the rounding used to keep the fractional bits to 52.

Also with this decimal number:

var x = new Number(.12345678912367890)

This number contains 68 fractional bits, hence the last zero is chopped off to keep 64-bit length.

Usually numeric representation larger than 9007199254740992 or smaller than 1.1102230246251565E-16 are stored as literal strings instead of Number. If you need to compute very large numbers, there are certain external libraries available to perform arbitrary precision arithmetic.

If you want to cast more then 16 points after the decimal point you can either:

Nbody
  • 1,168
  • 7
  • 33
  • By your description 52 bits for fraction ( fraction as I understand is digits which comes after .) 13 * 4 = 52 , which mean what it should only hold 13 digits after point, but as as described above , it seems like 14 digits , and also from what you have described as I understand 1 bit goes to store info about is it possitive or negative ? @n-ata – Andrey Radkevich Apr 15 '22 at 12:01