Mysterious numbers
I ran into something today that made me realize something weird and interesting.
Check out this code:
int number = GetMysteryNumber();
Console.WriteLine(number == -number);
int GetMysteryNumber() => ???;
What number can GetMysteryNumber
return that will display True
, aside from 0
?
0
obviously works because the negative of 0 is, mathematically, still 0.
But I wouldn’t be asking this question if there wasn’t another.
Figured it out?
The answer is int.MinValue
, or -2147483648
.
The reason comes down to the fact that computers can’t quite follow the actual rules of math.
An int
is intended to store an integer, but is limited to 32 bits or 4 bytes.
That means it cannot represent all mathematically valid integers.
For example, the smallest number an integer can represent is -2,147,483,648, and the largest number it can represent is +2,147,483,647.
So what happens when you do some math that exceeds the bounds of what your type can handle?
There’s a few options.
For a floating-point type, the number will jump to positive or negative infinity. You could call that a rounding error, but… that is some jump! Alas, that’s what you get when you push the limits too far.
For the integer types, what happens will depend on if you are running in a checked or unchecked context. In a checked context, which is not the default, you’ll get an exception. But let’s set aside the checked context thing for a moment, because it is somewhat rare to be running code in a checked context.
In an unchecked context, you simply wrap around.
int.MaxValue + 1
will be int.MinValue
, and int.MinValue - 1
will be int.MaxValue
.
Back to the original question.
Lets start with int.MinValue
: -2147483648
. If we negate that, we end up with +2147483648
.
But, uh oh! That’s too big! It overflows the maximum value for the int
type by one, and the result wraps around back to… int.MinValue
again.