The Case of the Disappearing Number

On a current project we were experiencing an issue with a specific numeric ID not working correctly. After some exhaustive debugging, it was isolated it to a seemingly bizarre phenomenon that manifests in both AS3 and Javascript: a missing number.

Specifically, we found that the number 10100401822940525 appears to simply not exist in these programming environment. You can test this for yourself, simply trace or log the following statements:
10100401822940524
10100401822940525
10100401822940524+1
Number(“10100401822940525”)
(10100401822940525).toString()

All of the above statements will output “10100401822940524”, when obviously all but the first one should return “10100401822940525”.

Theres no obvious significance to that value. The binary/hex value isn’t flipping any high level bit, and there are no results for it on google or Wolfram Alpha. Additional testing showed the same result with other numbers in this range.

I thought it might be related to the value being larger than the max 32bit uint value, but adding a decimal (forcing it to use a floating point Number) does not help, it simply rounds it up to “10100401822940526” instead. Number should support much higher values (up to ~1.8e308). I confirmed this with:
Number.MAX_VALUE > 10100401822940526 // outputs true

As it turns out, the issue is a side effect of how Numbers are stored. Only 53bits out of the 64bits in a Number are used to store an accurate value. The remainder are used to represent the magnitude of the value. You can read about this here. So, the maximum accurate value we can store is:
Math.pow(2,53) =
9007199254740992 < 10100401822940525 This means that the precise value is not stored. Knowing this, we can rework our logic to store the value in two uints / Numbers. Thanks to everyone on Twitter that provided input to this article. I'd name contributors individually, but I had a lot of duplicate responses, and don't want to leave anyone out.

Grant Skinner

The "g" in gskinner. Also the "skinner".

@gskinner

4 Comments

  1. The problem shouldn’t be an issue because “Number” is a floating point value. In AS, if you’re dealing with IDs, the notion of a floating point Number isn’t needed. You should instead be using uint. 2^52 isn’t the highest accurate value you can store with with floating point value, it’s the highest accurate integer value you can store with a floating point value. floating point values get their accuracy from the maximum number of trailing digits following the decimal which is always the same length.

  2. You can read more about how the numbers are stored on the IEEE 754 Wikipedia article. 🙂

  3. this is weird, now I know what are the numbers for the next draw on EuroMillions, lol!!! see you in maceio! tchauuu!

  4. That sounds like a programming nightmare. I have no idea how long it would take me to debug that, but congrats to you guys for doing so.

Comments are closed.