Help me figure out a weird integer storage thing?
The full story is pretty long, so here’s the tl;dr: why would something that is seemingly storing integers start storing only even numbers—rounding odd numbers to the closest even above them—once a particular threshold is exceeded?
The story: I work at a cafeteria, and sometimes I get assigned to cover breaks for the cashiers. I work the night shift so it can get quite slow, no customers for several minutes at a time. During one of these lulls, with nothing better to do, I start messing around with the buttons on the cash register, and I notice that there’s a “misc” option, that lets you add a charge for a custom amount. For the heck of it, I decide to test the limits of the software the cash register runs on, I spam the number nine in the input box (already way more than you could spend at the cafeteria, probably more than there is currency in circulation), I hit enter and the register handles it without a problem, displaying a charge for the full amount as I typed it in. Over a few minutes, I hone in on the max value the register will accept (it just throws an error when the number is exceeded), at first counting out nines to get the approximate length, then fiddling with the leading digits for precision. At some point while doing this, I realized I had enough digits to match the number to a power of two, since that would be a likely upper bound. I pull up a calculator on my phone and sure enough, after a few attempts to get into the right range, I find a match: 2^96. This is the first thing that strikes me as odd, I was expecting the number of bits to be a power of two, I know it doesn’t Need to be that way, just a common convention. Going back to the register, I try my luck with 2^96-1, but to my surprise, it gives me the out of bounds error, not really thinking about why this would work, I try 2^96-2, and for some reason it Does work. This was such a counterintuitive result at first that I concluded that I must have typed something in wrong the first time around and tried 2^96-1 again, still nothing. Next step was to double check 2^96-2, maybe I had missed a number, or accidentally substituted a smaller digit at some point? Nope. Curious, I try 2^95-1, and that’s when I realize that the register is rounding up to the next even number, displaying “…5168” instead of “…5167.” I decide that my next task is obvious: find where it transitions from including every positive integer, evens and odds, to only showing evens. 2^94-1? Rounds to an even. 2^93-1? Rounds to an even. But not 2^92-1, now we’re getting somewhere. I spend a few minutes doing a manual binary search and notice something interesting about the four largest terms: 2^92+2^91+2^88+2^87-1 did not round, but 2^92+2^91+2^88+2^87+2^86-1 did. Going out on a limb, I add up the powers of two congruent to zero or three modulo four up to 2^92 (from now on I’m calling this number n). n-1 doesn’t round, good start, and n+1… also doesn’t round. Rats. But then, paydirt: n+3 rounds up from 7922816251426433759354395035 to 7922816251426433759354395036. But now we come back to the question: why? My first thought was that maybe it was a way to squeeze a little extra range out of a fixed number of bits, but that doesn’t quite make sense, you would need to skip every other number starting at zero to get up to the power of two higher than the number of bits you have. Starting at 7.9 octillion in particular would, in getting to 2^96-2, overshoot the number of numbers you can represent with 95 bits by roughly 4 octillion (yeah, i know it’s just half of the value i gave for n, big numbers are just fun to say sometimes). Honestly, I’m at a loss here, I even considered maybe I was wrong about the value being stored as an integer, but if it is a float of some sort, I can’t figure out what the encoding would look like. I hope this was at least a little fun to read, it was an entertaining little project (even outside the context of being bored at work), but now I’m at a point where I don’t know how I would proceed on my own.
P.S. I did kinda stretch the truth in the story, that didn’t all happen in one sitting while I was covering a coworker’s shift, it was stretched out over several days, a few minutes at a time, I just didn’t feel like breaking up the narrative with “and then their break was over so I had to leave”