2

I'm reading Effective Javascript by David Herman, and just learned this about how JavaScript handles numbers:

"all numbers in JavaScript are double-precision floating-point numbers, that is, the 64-bit encoding of numbers specified by the IEEE 754 standard -- commonly known as "doubles". If this fact leaves you wondering what happened to the integers, keep in mind that doubles can represent integers perfectly with up to 53 bits of precision. All of the integers from -9,007,199,254,740,992 (-2^53) to 9,007,199,254,740,992 (2^53) are valid doubles." (p. 7)

I was curious, so I threw together this jsfiddle to try it out:

var hilariouslyLargeNumber = 9007199254740992;

console.log(hilariouslyLargeNumber);
// 9007199254740992
console.log(hilariouslyLargeNumber + 1);
// 9007199254740992

console.log (hilariouslyLargeNumber === hilariouslyLargeNumber);
// true
console.log(hilariouslyLargeNumber === hilariouslyLargeNumber+1);
// true
console.log(hilariouslyLargeNumber === hilariouslyLargeNumber-1);
// false

I sort of understand why this is the case -- in simple (simple, simple) language, there aren't any more 'slots' for any more 0s and 1s for how JavaScript encodes numbers, and so it has to stop at 9,007,199,254,740,992.

So: what do I do if I find myself in possession of 9,007,199,254,740,993 puppies, and want to write some code to help me remember which one is which? Do I need to use something other than JavaScript? If so, why?

mknadler
  • 208
  • 1
  • 8
  • 5
    Duplicate question: http://stackoverflow.com/questions/1725341/javascript-large-number-library -- basically, you need big.js or another large number library. – Graham Charles Aug 10 '14 at 20:06
  • That's a relief. I almost confused two of the malamutes. I guess the second, implied part of my question, which isn't covered there, is: *why* is this the case? I only barely understand the rationale behind this. – mknadler Aug 10 '14 at 20:08
  • 2
    Why is what the case – why do all of your comparisons result in true? Because with your numbers your are out of the range of integers, and therefor your values are treated as floats (and about their inherent imprecision you can read up on the web). – CBroe Aug 10 '14 at 20:16
  • I'll try to do some reading, but most of what I looked for (before posting this question, mind you :)) was a bit over my head. I'm not coming from a CS background and was never fantastic at math. A simple explanation of what is going on here would be appreciated -- "they're treated as floats" means *nothing* to me. – mknadler Aug 10 '14 at 20:31

2 Answers2

1

You have to do some work-around programming. An example would be:

var MAX_VALUE = 9007199254740992;

var lower_digit_set = 0;
var upper_digit_set = 0;


/* Do some calculations that will eventually result in lower_digit_set to be 9007199254740992 */

lower_digit_set = MAX_VALUE;

if (lower_digit_set == MAX_VALUE) {
    lower_digit_set = 0;
    upper_digit_set = upper_digit_set + 1;
}



/* What you have to keep in mid is that your final number is something you calculate,
   however you cannot display it (you probably could, but it is very complex solution that I should give it a longer thought).
   And therefore if we increase lower_digit_set as such: */

lower_digit_set = lower_digit_set + 1;

/* Then the new number will be a combination of both lower_digit_set and upper_digit_set*/

console.log("The actual number is more than once, or twice, or thrice ...etc. of the max_value");
console.log("Number of times we multiply the max value: ", upper_digit_set);
console.log("Then we add our remainder: ", lower_digit_set);

Please note, if you are going to calculate negative numbers, then you should account for that. Also, the solution depends on your needs, this is just an example, you may need to modify it to fit your needs, but it just gives you a general idea of what you need to do, or at least a way of thinking so to speak.

Greeso
  • 7,544
  • 9
  • 51
  • 77
  • It is highly risky to play with that just like so: Numbers are stored in IEEE standards for double etc as something to the power of something, which equals an even relative spacing. If you do use multiple numbers doing so at a lower point would (just giving it a very brief thought) raise the precision enormously! So first make sure you understand the underlaying model! – mike Aug 10 '14 at 21:47
0

Of course you can do it; you just can't do it with primitives. Libraries like JSDecimal represent numbers in other ways.

Chris Martin
  • 30,334
  • 10
  • 78
  • 137