What Is JavaScript'S Highest Integer Value That a Number Can Go to Without Losing Precision

What is JavaScript's highest integer value that a number can go to without losing precision?

JavaScript has two number types: Number and BigInt.

The most frequently-used number type, Number, is a 64-bit floating point IEEE 754 number.

The largest exact integral value of this type is Number.MAX_SAFE_INTEGER, which is:

  • 253-1, or
  • +/- 9,007,199,254,740,991, or
  • nine quadrillion seven trillion one hundred ninety-nine billion two hundred fifty-four million seven hundred forty thousand nine hundred ninety-one

To put this in perspective: one quadrillion bytes is a petabyte (or one thousand terabytes).

"Safe" in this context refers to the ability to represent integers exactly and to correctly compare them.

From the spec:

Note that all the positive and negative integers whose magnitude is no
greater than 253 are representable in the Number type (indeed, the
integer 0 has two representations, +0 and -0).

To safely use integers larger than this, you need to use BigInt, which has no upper bound.

Note that the bitwise operators and shift operators operate on 32-bit integers, so in that case, the max safe integer is 231-1, or 2,147,483,647.

const log = console.logvar x = 9007199254740992var y = -xlog(x == x + 1) // true !log(y == y - 1) // also true !
// Arithmetic operators work, but bitwise/shifts only operate on int32:log(x / 2) // 4503599627370496log(x >> 1) // 0log(x | 1) // 1

Is Number.MAX_SAFE_INTEGER has value of (2^53 - 1) in 32-bit computer

Yes. All JavaScript Numbers are represented using IEEE 754 binary64 (A.K.A. double precision floating point). This format takes 64 bits of space, but most modern 32-bit processors support it natively, and even if they didn't, it would be possible to implement floating point operations in software.

The "32-bit" in 32-bit processor refers to the word size.

What is the maximum integer allowed in a javascript variable?

JavaScript numbers are IEE 794 floating point double-precision values. There's a 53-bit mantissa (from memory), so that's pretty much the limit.

Now there are times when JavaScript semantics call for numbers to be cast to a 32-bit integer value, like array indexing and bitwise operators.

Calculation when number is 999999999999999

As you already discovered, you ran into an issue with the limited precision of floating point numbers, since your number is outside of the range of "safe integers" which are stored with full precision (it is larger than Number.MAX_SAFE_INTEGER = 2^53 - 1).

If you only need integers, the native BigInt type will work just fine (as long as you take care of converting things to/from a BigInt in the right way):

const result = 9999999999999999n + 2n
console.log(result) // 10000000000000001n (not printed in Stack Overflow somehow)

What's the point of having values above Number.MAX_SAFE_INTEGER?

everything in between the two values is not very useful, and it forces the developer to switch to BigInt.

It can be useful if absolute precision isn't required. When dealing with huge numbers, it's not very usual to require that much.

Take incremental games for an example. They often need to represent huge numbers, but the insignificant tail end of the values (for example, the thousands, when the numbers being dealt with are on the order of 1e20) isn't important and can be safely discarded without impacting functionality.

BigInts are a somewhat new thing too. Before it existed, it was useful to be able represent huge numbers even if they were sometimes slightly inaccurate with their least significant digits. Before BigInts, better to be able to represent huge numbers despite slight inaccuracy than to not be able to represent huge numbers at all.

Why does this number get increased by one?

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!



Related Topics



Leave a reply



Submit