8

console.log(10209761399365907);

Why does this code output a number greater by one (10209761399365908 instead of 10209761399365907)?

This is happening only for this specific number. For instance with 10155071933693662 I get the correct value (10155071933693662).

Is there something I need to know about that specific number? The only workaround I figured out is to pass the value as a string.

Michał Perłakowski
  • 88,409
  • 26
  • 156
  • 177
Ziba Leah
  • 2,484
  • 7
  • 41
  • 60
  • Hmm that sounds pretty weird. It also happens if you try to paste in the number in the dev console. Perhaps it has something to do with the number being too big? – Jon Snow Nov 29 '16 at 13:55
  • It's a Facebook ID, I store it as a LONG in C# – Ziba Leah Nov 29 '16 at 13:56
  • 4
    Related (maybe even a duplicate): [What is JavaScript's highest integer value that a Number can go to without losing precision?](http://stackoverflow.com/q/307179/3853934) – Michał Perłakowski Nov 29 '16 at 16:15
  • 2
    @Gothdo I don't think the edits you made to this question were a good idea. Specifically, you removed the originally posted HTML markup and the fairly important point of explicitly using a string in the element's event handler attribute value. – Pointy Nov 29 '16 at 16:36
  • @Pointy Why? I removed lots of unnecessary information. Did I remove something relevant to the question? – Michał Perłakowski Nov 29 '16 at 16:37
  • @Gothdo the OP was asking about particular markup, and my accepted answer provided the revised version. – Pointy Nov 29 '16 at 16:38
  • @Pointy But the issue is not specific to this particular markup. I think after my edit it's more readable to other users. – Michał Perłakowski Nov 29 '16 at 16:41
  • @Gothdo yep, totally a duplicate. We don't need yet another question about "why is my number less accurate than I'd like" – John Dvorak Nov 29 '16 at 16:44
  • 1
    @JanDvorak I don't mind closing it as a duplicate, but overwriting the original content of the question means that nobody will chance on this question and the linked duplicate as a serendipitous result of performing searches based on that content. – Pointy Nov 29 '16 at 16:45

1 Answers1

19

Your numeric value is too large to be represented exactly as a 64-bit floating point number. The value you get is an approximation. JavaScript natively only has 64-bit floating point numbers; values that do fit in a long in C or C++ may be too large to be represented exactly because some of the 64 bits are used for an exponent in floating point representation. (The tradeoff is that with a floating point it's possible to work with approximations for values with much larger or smaller numeric magnitude than is possible with simple integer representation.)

If it's not important to manipulate the value as a number, make it a string:

console.log("10209761399365907");

or as I suggested for the question as it originally appeared:

<input type="button" value="Invita" onclick="Invite('@us.FacebookID')" />

where that "FacebookID" was the big number in question.

There's a constant (in newer JavaScript environments) called Number.MAX_SAFE_INTEGER. That tells you how big a number you can represent such that the value will be represented exactly; that is, that the 64-bit floating point mantissa will contain explicit bits for the entire value.

Larger even integers can be represented exactly, depending on how many zero bits are at the low end of their binary representation. Thus, 1152921504606846800 can be exactly represented because it's got 7 bits of all zeros at the low end of the binary representation. However, 1152921504606846801 comes out as 1152921504606846800 because that low 1 bit has nowhere to go. (Unrepresented bits are assumed to be zero.)

Addendum: Here's the (almost) original version of the question as posed, to explain the possibly confusing example code above:


I'm facing a problem with Javascript that is quite weird. I have some ids coming from my server and when I press a button the parameter is passed to a method to perform a request.

This is the code:

<script type="text/javascript">
function Invite(id)
{
    alert(id);
}
</script>

On the other hand, I have:

(CSHTML syntax)

 <input type="button" value="Invita" onclick="Invite(@us.FacebookID)" />

That became:

<input type="button" value="Invita" onclick="Invite(10209761399365907)">

But when I click the button... the number the method receives the parameter INCREASED by ONE!

Alert from CODE

And this is happening ONLY for one specific ID! For instance, with 10155071933693662 I get the correct value (10155071933693662)

Is there something I need to know about that specific number? All this is really strange and the only workaround I figured out is to pass the value as a string!

Farzad Karimi
  • 770
  • 1
  • 12
  • 31
Pointy
  • 405,095
  • 59
  • 585
  • 614
  • Mate, `10209761399365908` and `10209761399365906` returns the right value. Why only `10209761399365907`? – Praveen Kumar Purushothaman Nov 29 '16 at 13:57
  • 4
    @PraveenKumar that's because there are bits dropped on the right hand side. Type `Number.MAX_SAFE_INTEGER` into your browser console and compare it to this value in the question. – Pointy Nov 29 '16 at 13:57
  • 4
    @PraveenKumar and those are even numbers. What are the low bits in the binary representation of those, I wonder? – Pointy Nov 29 '16 at 13:58
  • 3
    'Large' in this context doesn't mean 'larger number' but 'larger representation in bits'. – roberrrt-s Nov 29 '16 at 13:59