I came across an interesting problem today where a cast from
int resulted in
Further digging revealed that it was a
How did I get a
NaN in simple C#? Damn divide by zero, that’s how.
But wait, how did I not get an exception?
double first = 0; double second = 0; var result = (int)Math.Round(first / second);
In the above case,
-2147483648, but why! Feels like an overflow, so expanding it out, I got:
double first = 0; double second = 0; var division = first / second; // NaN var rounded = Math.Round(division); // NaN var result = (int)rounded; // -2147483648
There it is! Divide by zero gives
NaN and casting that to
int gives the minimum.
Seems strange…The documentation clarifies it for me though.
When you convert a double or float value to an integral type, this value is rounded towards zero to the nearest integral value. If the resulting integral value is outside the range of the destination type, the result depends on the overflow checking context. In a checked context, an OverflowException is thrown, while in an unchecked context, the result is an unspecified value of the destination type.
Basically, by default I was in an
unchecked context, which means variables don’t get checked for overflow. Numeric casting in
unchecked contexts always succeeds, with the result being an unspecified value. Could have been anything, could have been that when this code was written, the writer was getting the 0 they wanted.
The fix I went for was to check whether the result was
NaN and if so, just return 0 instead.
I shared this with my colleagues, and we discovered that
0/0 is different to
n/0, which is infinity and also casts to
Surprising that C# lets us fall into that trap!