1

Why is it apparently safe to use numbers as integers in Javascript? What I mean is that a loop such as the one below is generally "trusted" to run the expected number of times even though the final loop requires an exact compare of (10000 == 10000) when these two values are floats and not ints. Is there some sort of built-in rounding feature that makes this safe and reliable -- or is this horrible and untrustworthy coding? Thanks.

--edit--

It is interesting that there is a declared safe integer range. I was not aware of MAX_SAFE_INTEGER. We all know the standard whine that 2 + 2 = 3.9999. I note that MAX_SAFE_INTEGER is listed as ECMAScript-6 so does this imply that IEEE-754 does not actually mention a safe integer range?

var cnt = 0;
for (var i=0 ; i<=10000 ; i++){
  // loop 10001 times
  cnt++;
}
alert('cnt = '+ cnt);
davej
  • 165
  • 1
  • 6
  • 3
    See: [What is JavaScript's highest integer value that a Number can go to without losing precision?](http://stackoverflow.com/questions/307179/what-is-javascripts-highest-integer-value-that-a-number-can-go-to-without-losin) That loop is guaranteed to be safe. – Jeremy Mar 17 '15 at 18:12
  • `Number.MAX_SAFE_INTEGER; // 9007199254740991`, don't forget that in _JavaScript_ you use `===` for equality and `==` for _abstract equality_ – Paul S. Mar 17 '15 at 18:12
  • 2
    @floor strict mode doesn't have any effect on JavaScript's data types (at least, not in the sense we're discussing here). – Jeremy Mar 17 '15 at 18:13
  • @JeremyBanks Yep your right, I feel stupid now. I swear I read somewhere that you could enable other data types in javascript. – floor Mar 17 '15 at 19:13

2 Answers2

1

IEEE-754 double-precision floating point numbers (the kind used by JavaScript) have a very wide range over which they precisely represent integers, specifically -9,007,199,254,740,991 through 9,007,199,254,740,991. (Those values are being added to JavaScript's Number function as constants: MIN_SAFE_INTEGER and MAX_SAFE_INTEGER.) Outside that range, you could indeed run into trouble.

In fact, if it weren't for safety, this loop would never end:

var n, safety;
safety = 0;
for (n = 9007199254740990; n != 9007199254740999; ++n) {
  if (++safety === 20) { // Long after `n` should have matched
    snippet.log("Had to break out!");
    break;
  }
  snippet.log("n = " + n);
}
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
0

Firstly, the final loop doesn't require the two values to be equal. Just that i is less than 10000.

Secondly, the Number type in JavaScript holds integer values accurately up (and down) to a point. You can access the Number.MAX_SAFE_INTEGER and Number.MIN_SAFE_INTEGER properties to see what the safe range is for your browser/engine.

And if you want to check if an instance of Number is an integer, just use the Number.isInteger() method.

var i = 10, e = document.getElementById('message');
if(Number.isInteger(i)) {
  e.innerHTML = "i is an integer";
} else {
  e.innerHTML = "i is not an integer";
}
<div id='message'></div>
Justin Niessner
  • 242,243
  • 40
  • 408
  • 536
  • 1
    I'm not sure I'd exactly say that it "holds integer values" -- that makes me think of distinctly-tagged values. Integer support is a side effect of the fact that standard floats can represent a range of integer values accurately. This is the same behaviour that you'd get anywhere you use standard floats. – Jeremy Mar 17 '15 at 18:16
  • @JeremyBanks - Changed the wording to be more clear. – Justin Niessner Mar 17 '15 at 18:19