What is JavaScript's highest integer value that a number can go to without losing precision?
Solution 1
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.
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.log
var x = 9007199254740992
var y = -x
log(x == x + 1) // true !
log(y == y - 1) // also true !
// Arithmetic operators work, but bitwise/shifts only operate on int32:
log(x / 2) // 4503599627370496
log(x >> 1) // 0
log(x | 1) // 1
Technical note on the subject of the number 9,007,199,254,740,992: There is an exact IEEE-754 representation of this value, and you can assign and read this value from a variable, so for very carefully chosen applications in the domain of integers less than or equal to this value, you could treat this as a maximum value.
In the general case, you must treat this IEEE-754 value as inexact, because it is ambiguous whether it is encoding the logical value 9,007,199,254,740,992 or 9,007,199,254,740,993.
Solution 2
>= ES6:
Number.MIN_SAFE_INTEGER;
Number.MAX_SAFE_INTEGER;
<= ES5
From the reference:
Number.MAX_VALUE;
Number.MIN_VALUE;
console.log('MIN_VALUE', Number.MIN_VALUE);
console.log('MAX_VALUE', Number.MAX_VALUE);
console.log('MIN_SAFE_INTEGER', Number.MIN_SAFE_INTEGER); //ES6
console.log('MAX_SAFE_INTEGER', Number.MAX_SAFE_INTEGER); //ES6
Solution 3
It is 253 == 9 007 199 254 740 992. This is because Number
s are stored as floating-point in a 52-bit mantissa.
The min value is -253.
This makes some fun things happening
Math.pow(2, 53) == Math.pow(2, 53) + 1
>> true
And can also be dangerous :)
var MAX_INT = Math.pow(2, 53); // 9 007 199 254 740 992
for (var i = MAX_INT; i < MAX_INT + 2; ++i) {
// infinite loop
}
Further reading: http://blog.vjeux.com/2010/javascript/javascript-max_int-number-limits.html
Solution 4
In JavaScript, there is a number called Infinity
.
Examples:
(Infinity>100)
=> true
// Also worth noting
Infinity - 1 == Infinity
=> true
Math.pow(2,1024) === Infinity
=> true
This may be sufficient for some questions regarding this topic.
Solution 5
Jimmy's answer correctly represents the continuous JavaScript integer spectrum as -9007199254740992 to 9007199254740992 inclusive (sorry 9007199254740993, you might think you are 9007199254740993, but you are wrong! Demonstration below or in jsfiddle).
console.log(9007199254740993);
However, there is no answer that finds/proves this programatically (other than the one CoolAJ86 alluded to in his answer that would finish in 28.56 years ;), so here's a slightly more efficient way to do that (to be precise, it's more efficient by about 28.559999999968312 years :), along with a test fiddle:
/**
* Checks if adding/subtracting one to/from a number yields the correct result.
*
* @param number The number to test
* @return true if you can add/subtract 1, false otherwise.
*/
var canAddSubtractOneFromNumber = function(number) {
var numMinusOne = number - 1;
var numPlusOne = number + 1;
return ((number - numMinusOne) === 1) && ((number - numPlusOne) === -1);
}
//Find the highest number
var highestNumber = 3; //Start with an integer 1 or higher
//Get a number higher than the valid integer range
while (canAddSubtractOneFromNumber(highestNumber)) {
highestNumber *= 2;
}
//Find the lowest number you can't add/subtract 1 from
var numToSubtract = highestNumber / 4;
while (numToSubtract >= 1) {
while (!canAddSubtractOneFromNumber(highestNumber - numToSubtract)) {
highestNumber = highestNumber - numToSubtract;
}
numToSubtract /= 2;
}
//And there was much rejoicing. Yay.
console.log('HighestNumber = ' + highestNumber);
ImaginaryCake
Seth A. Roby is curious about everything. He writes Ruby, JavaScript, and Objective-C all day, and wishes IE would quietly disappear from the face of the earth. He lives in Costa Mesa, California with his wife, two daughters, one son, and two cats. He's pretty awesome; you'd like him.
Updated on March 02, 2022Comments
-
ImaginaryCake over 2 years
Is this defined by the language? Is there a defined maximum? Is it different in different browsers?
-
Dmitri Zaitsev about 8 yearsYou don't need to depend on JS's limits with libraries like github.com/MikeMcl/big.js, see e.g. here for its reliability tests
-
George over 6 yearswhat's the highest integer value you can use with big.js ?
-
simhumileco almost 6 years@George Here is big.js API: mikemcl.github.io/big.js/#dp
-
Veky over 5 yearsThe question doesn't make sense. What does it mean that a number "goes to" an integer value? If you just want to ask what is the highest integer you can represent in JS, the highest (finite) Number itself is an integer.
-
Amadan over 4 years@DmitriZaitsev We don't need to depend on external libraries any more (on some browsers, at least).
1n << 10000n
is a really, really big integer, without losing any precision, without requiring any dependencies (and needless to say, not even close to a limit). -
Dmitri Zaitsev over 4 years@Amadan Where does
1n << 10000n
come from here? -
Amadan over 4 years@DmitriZaitsev Just a random example of a big number.
-
Dmitri Zaitsev over 4 years@Amadan So how can this random number remove the need for external libraries?
-
Amadan over 4 years@DmitriZaitsev Notice the
n
suffix.BigInt
class is a part of ES2020 spec draft, already implemented in the majority of browsers; you can try to evaluate that in e.g. Chrome or Firefox, with no external libraries, and get a 3011-digitBigInt
. -
Dmitri Zaitsev over 4 years@Amadan It is only for integers. E.g. how do you add
.1+.2
precisely? -
Amadan over 4 years@DmitriZaitsev: Yes, it is only for integers. This question is about integers.
-
-
ImaginaryCake over 15 yearsI've edited the question to be a bit more precise about wanting the max Integer values, not just the max Number value. Sorry for the confusion, here.
-
ImaginaryCake over 15 yearsThis seems right, but is there someplace where this is defined, á la C's MAX_INT or Java's Integer.MAX_VALUE?
-
Wedge over 15 yearsNote that 9e15 = 2^53 (see @Jimmy's answer).
-
Boti over 15 yearsits not a 64 bit integer, its a 64-bit floating point number, of which 52/53 bits are the integer portion. so it will handle up to 1e300, but not with exact precision.
-
Boti over 15 yearsaccording to IEEE_754 standard, 64-bit floating point uses 53 bits for the mantissa. As far as a javascript constant, I'm not aware of any.
-
coolaj86 almost 13 years
4294967295 === Math.pow(2,32) - 1;
-
Ryan over 12 yearsJimmy is correct. Try this in your browser or JS command line:
100000000000000010 - 1 => 100000000000000020
-
Pacerier over 12 yearsSo what's the smallest and largest integer we can use to assure exact precision?
-
Boti over 12 yearsfor simple operations,
2^53
as the first part of my answer states. I've edited to make the answer more clear -
Beetroot-Beetroot almost 12 yearsMaybe worth noting that there is no actual (int) in javascript. Every instance of Number is (float) or NaN.
-
devios1 almost 12 yearsSomething tells me infinity doesn't qualify as an integer. :)
-
devios1 almost 12 years9e15 = 9000000000000000. 2^53 = 9007199254740992. Therefore to be pedantic, 9e15 is only approximately equal to 2^53 (with two significant digits).
-
djjeck over 11 yearsBut it's good enough to initialize a
min
variable when you're looking for a minimum value. -
skeggse over 11 years@Beetroot-Beetroot Or +/- Infinity
-
Briguy37 over 11 years@CoolAJ86: Lol, I'm looking forward to March 15, 2040. If our numbers match we should throw a party :)
-
Roy Tinker over 11 years-1: the maximum representable (non-exact integral) number may be ~2^1024, but that doesn't mean they're deviating from the IEEE-754 64-bit standard.
-
Boti about 11 years@LucioM.Tato Question specifically asks for "without losing precision" Number.MAX_VALUE is the "largest value, period" but for example,
Number.MAX_VALUE - 1
is not a valid value. -
Raul Guiu about 11 yearsMAX_INT? Do you mean MAX_VALUE?
-
phuclv almost 11 yearsthat's maximum of a floating point value. It doesn't mean that you can store an int that long
-
Pacerier almost 11 yearsIs the returned result guaranteed to be equal on all browsers?
-
H.Wolper over 10 yearsNote that
Infinity - 1 === Infinity
-
Sijav over 10 yearsalso (Infinity<100) => false and Math.pow(2,1024) === Infinity
-
BananaNeil over 10 yearsThe Math.pow(2,1024) === Infinity is awesome. going to add that one.
-
Royi Namir over 10 years@chaiguy In
9000000000000000
there is 1 significant figure. in ` 9007199254740992` there are 15 significant figures. -
devios1 over 10 years@RoyiNamir Not wanting to start a pointless argument here, but 9000000000000000 has 16 significant digits. If you want only 1, it would have to be written as 9x10^15.
-
Royi Namir over 10 years@chaiguy No.
9000000000000000
as it is - has1
SF. where90*10^14
has 2. (sigfigscalculator.appspot.com) & mathsfirst.massey.ac.nz/Algebra/Decimals/SigFig.htm (bottom section) -
MickLH over 10 yearscant you just start it at 2^53 - 2 to test? (yes you can, I just tried it, even with -3 to be safe: var x=Math.pow(2,53)-3;while (x!=x+1) x++;) -> 9007199254740991
-
MickLH over 10 yearsvar x=Math.pow(2,53)-3;while (x!=x+1) x++; -> 9007199254740991
-
Briguy37 over 10 years@MickLH: I get 9007199254740992 with that code. What JavaScript engine are you using to test?
-
MickLH over 10 yearsYou get 9007199254740992 with your own code, I did not use the final value of x, but the final evaulation of x++ for paranoid reasons. Google Chrome btw.
-
Charlie Affumigato over 10 yearsThis is the answer I wanted to stumble upon on how to convert X to a 32 bit integer or unsigned integer. Upvoted your answer for that.
-
peterflynn over 10 years@MickLH: evaluating
x++
gives you the value of x before the increment has occurred, so that probably explains the discrepancy. If you want the expression to evaluate to the same thing as the final value of x, you should change it to++x
. -
MickLH over 10 yearsThank you but I do know the semantics of the post-increment, and used it's "final evaluation" (as opposed to the final value of x) because it provides the number where (x!=x+1) aka the "last number where +1 works" as opposed to the "first number where it fails"
-
Briguy37 over 10 years@MickLH:
"last number where +1 works" == "max number w/out losing precision" - 1
-
MickLH over 10 years1. the question has an accepted answer so your implication to something I did not say is either wrong or useless, objectively. 2. the purpose of my comment is to show that the large algorithm you wrote is a rather useless waste of time, good day sir. (I am sorry that you take such offense to my explaining of my concept with a highly related algorithm that also serves a purpose which is actually useful to me, also it does calculate the same X ;) )
-
Briguy37 over 10 years@MickLH: Ok, I completely misunderstood what you were trying to say. I thought your first algorithm was to show that 9007199254740991 was the correct answer. Instead, it was to show that mine was a useless waste of time. I'm glad we cleared that up...
-
MickLH over 10 yearsbut love you bro, don't make it out like im the evil ass who don't appreciate dat efficiency
-
MickLH over 10 yearsEvery instance of Number is (float) <stop here> "or NaN." ... "Or +/- Infinity": Redundant, IEEE-754 (float) encodes NaN and +/-Infinity as part of the format. Also -0
-
kumarharsh over 10 years@danorton: I'm not sure you understand what you are doing.
^
means raised to the power. In the javascript console,^
is XOR, not raised-to -
danorton over 10 years@Kumar, I don’t understand your meaning or how any other meaning of “^” is relevant here in this question about JavaScript.
-
kumarharsh over 10 yearsopen Chrome/Firefox console. Type 5^2. In binary, 5 is
101
and 2 is010
. Now, if you Bitwise XOR them, you'll get5(101) ^ 2(010) = 7(111)
READ THIS IF YOU'RE CONFUSED What is being discussed here isMath.pow()
not the^
operator -
danorton over 10 yearsAgain, I am not at all confused. I have commented and downvoted on what is written. If Math.pow() is what is meant, then that is what should be written. In an answer to a question about JavaScript, it is inappropriate to use syntax of a different language. It is even more inappropriate to use a syntax that is valid in JavaScript, but with an interpretation in JavaScript that has a different meaning than what is intended.
-
higuaro over 10 yearsNice answer! Moreover, I know the value is settled, but why not use binary search for its finding?
-
coolaj86 over 10 yearsWhat's the fun in that? Besides, @Briguy37 beat me to it: stackoverflow.com/a/11639621/151312
-
lmm over 10 years2^31 is how one writes two to the thirty-first power in English. It's not in a code block. Would you complain about someone using a ; in an answer, because that's a character with a different meaning in Javascript?
-
rvighne over 10 years@TALlama In ES6, there will be a constant for that:
Number.MAX_SAFE_INTEGER
(already landed in Chrome with experimental JS on). For now this answer is fine. -
Jerry about 10 yearsnote that this 'safe' MAX_INT based on 32 bits will not work when comparing with Date values. 4294967295 is so yesterday!
-
Michael Scheper about 10 yearsNote that
Number.MIN_VALUE
is the smallest possible positive number. The least value (i.e. less than anything else) is probably-Number.MAX_VALUE
. -
IMSoP about 10 yearsOr more to the point, you can't reliably store an int that long without loss of accuracy.
2^53
is referred to asMAX_SAFE_INT
because above that point the values become approximations, in the same way fractions are. -
Teepeemm almost 10 yearsThis is the maximum floating point value. The question is about the highest integer value. And while
Number.MAX_VALUE
is an integer, you can't go past2^53
without losing precision. -
Peter Bailey almost 10 years@Teepeemm This is a nearly six-year-old answer to a nearly six-year-old question, so it's curious that you'd care about sharp-shooting it now. But, if you care to look at the edit history, you'll see that the original question didn't specify integers stackoverflow.com/posts/307179/revisions, not to mention the OP's comment just 4 comments up where he mentions making this edit/clarification.
-
Willem D'Haeseleer almost 10 years9007199254740992 is not really the maximum value, the last bit here is already assumed to be zero and so you have lost 1 bit of precision. The real safe number is 9007199254740991 ( Number.MAX_SAFE_INTEGER )
-
superlukas almost 10 yearsES6 introduces
Number.MIN_SAFE_INTEGER
andNumber.MAX_SAFE_INTEGER
-
dmccabe over 9 yearsAlso worth nothing that it does handle negative Infinity too. So
1 - Infinity === -Infinity
-
Mark Amery over 9 years-1; I simply found this confusing. Sometimes I appreciate humour answers, but I think that this whole topic is complicated enough - especially given that some readers may not know that integers are stored as floats in JavaScript, or understand floating point imprecision - that adding a "fun" answer to the page that intermixes true claims and good advice with silliness is a harmful move. Also, perhaps I just have a bad sense of humour, but I didn't find it funny.
-
Mark Amery over 9 yearsAdditionally, I'm still completely unsure what the "expected issues with bit-shifting" are.
-
coolaj86 over 9 yearsThe answer "To be safe: var MAX_INT = 4294967295;" isn't humorous. If you're not bitshifting, don't worry about it (unless you need an int larger than 4294967295, in which case you should probably store it as a string and use a bigint library).
-
jkdev over 9 years
-
K Lee over 9 yearsBy the way, that number reads as: nine quadrillion , seven trillion , one hundred ninety nine billion , two hundred fifty four million , seven hundred forty thousand , nine hundred ninety one
-
cregox about 9 yearsBeware this is not (yet) supported by all browsers! Today iOS (not even chrome), Safari and IE don't like it.
-
WaiKit Kung about 9 yearsPlease read the answer carefully, we are not using the default implementation of Number.MAX_SAFE_INTEGER in ECMAScript 6, we are defining it by Math.pow(2, 53)-1
-
cregox about 9 yearsI thought it was just a reference to how it is implemented in ECMA 6! :P I think my comment is still valid, though. All a matter of context. ;)
-
kjv about 9 yearsIs it reliable to calculate
MAX_SAFE_INTEGER
in all browsers by working backwards? Should you move forwards instead? I.e., Number.MAX_SAFE_INTEGER = 2 * (Math.pow(2, 52) - 1) + 1; -
rocketsarefast about 9 yearsSo, in this case, should we down vote the answer because it is wrong for the updated question, or leave it because the Peter Baily was right at the time it was answered?
-
Jocke about 9 yearsEven though one should write 2³¹ and not 2^31 in plain text its common to do so, because most keyboard layouts doesn't have those characters by default. At least I did not have any problems understanding what was meant in this answer.
-
ninjagecko almost 9 yearsthough one would never reach the end of that for loop in a sane timeframe, you may wish to say
i += 1000000000
-
Ted Bigham over 8 years@ninjagecko, he starts at MAX_INT so the end is right there. Also using i+= 1000000000 would make it no longer an infinite loop. Try it.
-
ninjagecko over 8 years@TedBigham: Ah oops, was ready too quickly through that. Thanks for correcting me twice.
-
Evgeni Nabokov over 8 yearsAnybody explain me one thing. "The MAX_VALUE property has a value of approximately 1.79E+308 (developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…). 1.79E+308 is a very big number which is much bigger than 2^53. What does mean Number.MAX_VALUE?
-
Boti over 8 years@EvgeniNabokov: Number.MAX_VALUE is the largest value representable by a 64-bit float. However, a 64-bit float cannot represent all integers less than 1.79E+308 (as you probably know, 64-bits can only represent 2^64 = 1.84E+19 unique values). Number.MAX_SAFE_VALUE, or 9007199254740991, has the property that every positive integer <= 9007199254740991 is exactly representable by a 64-bit float without losing precision. You can see in my code snippet in the answer that for values of x greater than 9007199254740991, you can have
x == x + 1
, which means we are losing precision. -
Admin almost 8 yearsin math infinite is not a number, is a concept
-
Laxmikant Dange over 7 yearsMax Value: Math.pow(2,1023)*1.9999999999999998
-
Ciprian Tomoiagă over 7 years+1 for specifying the limitations of bitwise operators !! It completely eludes me why on earth they chose to use 32-bit there, since it obviously uses 64 for Number.
-
ioquatix over 7 yearsIs
Math.pow(2, 53)-1
a safe operation? It goes one larger than the largest safe integer. -
Kyle Delaney about 7 yearsSo in UNIX milliseconds, that'll be October 12, 287396.
-
tsh almost 7 yearsa special case is
>>>
is defined onuint32_t
notint32_t
. -
Marie almost 7 yearsCouldnt you speed this up a lot by starting with a big value and only testing smaller values when you lose precision? Instead of adding 1 per loop lol
-
Bodo Thiesen almost 7 years@CiprianTomoiaga: Because 80386 was a 32 bit cpu and couldn't do that operations on 64 bit. And 80387 doesn't have shift operations. Please remember, that JS dates back a bit ...
-
Jules over 6 years@Pacerier - a good question that has been ignored: the answer happens to be yes: all conforming implementations of ECMAscript are required to behave as if Numbers are stored as IEEE 754 double precision floating point numbers, so all implementations should give the same answers for these constants.
-
Peter Bailey over 6 years@rocketsarefast I updated the text of the answer to include ES6 information, but you can vote however you like. I think there is sufficient information and conversation here that votes at this stage, for a question/answer this old, are basically like no-ops.
-
supercat about 6 years@BodoThiesen: Was there ever a time when extending bitwise operators out to 53 bits would have had any meaningful adverse effect on Javascript performance? In the early days of Javascript when 32-bit CPUs ruled the roost, performance would be constrolled more by the speed of the interpreter and symbolic lookup than anything having to do with actual numeric operations.
-
Marty ZHANG about 6 yearsWhy it's 53-bit when the document says there are 52 bits to hold the fraction? I think it's worth mentioning the reason behind this (at least I wasn't smart enough to figure it out by myself), this article explains it near its "Examples of how integers are stored" section.
-
Bodo Thiesen almost 6 years@supercat, I didn't say, I believe this was a "good" reason, I just said, I belive, this WAS the reason. And people sometimes tend to optimize at the wrong places. Anyway: Doing the shift on a double value create the need to either convert it to integer and back or heavy rounding prior to and after the shift. And yes: Doing a 64 bit shift would be only one instruction more than doing a 32 bit shift.
-
Boti almost 6 years@T.J.Crowder that's just a different definition of "losing precision", and I think a more unsafe one to use as a general principle. The IEEE-754 representation for the value 9007199254740992 is the same as representation for the value 9007199254740993, so if you ever have this bit pattern, you have to treat it as an inexact value since you can't be sure which of the two values it means.
-
T.J. Crowder almost 6 years@Jimmy - It's all a bit arbitrary. :-) But I like your reasoning, though I quibble with "The IEEE-754 representation for the value 9007199254740992 is the same as representation for the value 9007199254740993..." There isn't any representation for 9007199254740993, at all. It's not that it's the same as 9007199254740992; there isn't one. So anything trying to use that value has to go down to 9007199254740992 or up to 9007199254740994. (cont'd)
-
T.J. Crowder almost 6 years(continuing) But separately, in support of your definition: 9007199254740991 is the last value for which there's a bit for the 1's place; as of 9007199254740992, the least significant bit is the 2's place. Thus, loss of precision. So yeah, different ways to look at it, but I like your point. :-) Perhaps fold some of this into the answer? Since 9007199254740992 is held precisely...
-
T.J. Crowder almost 6 yearsSee Jimmy's argument for 9,007,199,254,740,991 instead of 9,007,199,254,740,992 here. That, combined with my follow-up, seems persuasive.
-
Galaxy almost 5 yearsThanks for the note on "bitwise operators and shift operators operate on 32-bit ints". Just noticed 1073741824 * 2 is 2147483648 but 1073741824 << 1 is -2147483648
-
Gershom Maes almost 5 yearsI was gonna say :^) but this made me realize it's no more than a disgusting syntax error
-
Sapphire_Brick over 4 yearsIt might crash your application, thought.
-
Andrew about 4 years@devios1 Actually it is an integer, it's equal to
Infinity - 1 + 1
. -
Dominic over 3 yearsHow do we calculate the maximum number given a certain amount of decimal places?
-
Boti over 3 years@Dominic There is no number of decimal places X > 0 such that all decimal numbers to that precision are representable. for example, 0.1 decimal has no exact representation in binary and cannot be exactly represented by floats
-
Daira Hopwood over 3 yearsThis answer as it currently stands is incorrect because it is implying that MAX_SAFE_INTEGER and MAX_VALUE both answer the question, and that the difference is only in which ES versions support them. In fact only MAX_SAFE_INTEGER correctly answers the question as it stands, and only MAX_VALUE answered the question as it was originally posted. MIN_SAFE_INTEGER and MIN_VALUE are irrelevant to the precise question.
-
Daira Hopwood over 3 yearsYes, this computation is correct.
Math.pow(2, 53)
is exactly representable, and the subtraction is well-defined and exact. -
JimbobTheSailor over 3 yearsThis is an important point. It is why I am here googling max int size. Other answers suggest 53 bits, so I coded it up thinking I could do bit wise arithmetic of positive values safely up to 52 bits. But it failed after 31 bits. Thanks @Marwen
-
Ben Bryant almost 3 yearsbad advice. You commonly want numbers over 4 billion like file sizes, but you don't need numbers over 9000 trillion. Bitwise operations were not in the question.