Software, technology, sysadmin war stories, and more. Feed
Wednesday, February 3, 2021

Push some big numbers through your system and look for bugs

If you use JSON anywhere, I want you to try something. Pop open the developer tools in your web browser and ask it to tell you what the result of 'Math.pow(2,60)' is. Just stuff that there and look at what you get back. It's a big number, right?

Now, using any other reference source, look up what 2 to the power of 60 is (hint: Wikipedia "power of two" if your Google search only gives you scientific notation). Compare it to what you got from your browser.

What did you find? I assume if you didn't notice the "000" on the end of what your web browser told you before, you will now.

Feel free to try this with other large numbers. You should find that anything above 2^53 starts getting squirrelly.

Exactly WHY this happens is not important for this specific post - floating point, mantissa, yadda yadda. I've covered it elsewhere, but I don't think people really appreciated it for the problem that it is. This method of approaching it should get the general concept around to a wider audience, or at least, I hope it will.

Why does this matter? Okay, let's say you have a JSON message where you pass around the unique ID of some object in your system. Let's further say that your system "mints" IDs out of a 64 bit number space, and it spreads them around, so large numbers can turn up every now and then.

What happens when you finally get an object ID with a value of 1152921504606846976 and put it into a message?

I mean, it's easy enough to try it yourself, like this:

JSON.parse('{ "a" : 1152921504606846976 }');

Fun, right? If you've been seeing numbers that have been "shaved off" in your systems, this might just be why.

Here's another interesting caveat: maybe you don't actually have JavaScript anywhere in your pipeline, but it's still happening. Odds are, you *do* have JSON in there somehow, and something not-Javascript is faithfully representing what'll happen to that large value when stuffed into a float like JS would, and the same problem happens.

Of course, if you have neither JavaScript nor JSON in your data processing pipeline and you're *still* seeing values being shaved down to 53 bits of precision, then perhaps there's a double hidden in there somewhere.

You really owe it to yourself to pump some numbers up around 2^60 through your stuff and see what happens on the other end.

Have fun!