Casting NaN to Numerics

I came across an interesting problem today where a cast from double to int resulted in int.MinValue.
Further digging revealed that it was a NaN problem.

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?

I had:

double first = 0;
double second = 0;
var result = (int)Math.Round(first / second);

In the above case, result was -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 -2147483648.

Surprising that C# lets us fall into that trap!

Tags: c-sharp