Jamie Ide Jamie Ide - 1 month ago 5
C# Question

Why is Nan (not a number) only available for doubles?

I have a business class that contains two nullable decimal properties. A third property returns the result of multiplying the other two properties. If HasValue is true for the two nullable types then I multiply and return the result. I have a few options for the return value if one or both of the properties is null:


  • Return 0

  • Throw an exception

  • Return a magic number (-1)

  • Return decimal? (EDIT -- see comments)



I thought one of my options would be to return NaN, but I see that this is only possible for the double type. Why is this?

For the record, returning 0 makes the most sense in this case and that's what I plan to do unless someone has a better suggestion.

Answer

Integral types in .NET use two's complement system for representation. While they could reserve some bit patterns for special values, they chose not to. double and float use a completely different representation system (IEEE 754) which reserves some special bit patterns for NaN, +Infinity, -Infinity, ...

One reason that NaN and Infinity values make more sense for floating point arithmetic is that operations could result division by zero, not only because the divisor is actually zero, but because it's too small to be represented by the type. As a result, if that wasn't the case, you could have some valid calculation mysteriously throw a divide by zero exception. This won't happen for int types as they are exact and don't have a precision error.

decimal is designed to be used for "real-world" decimal floating point numbers. It's rarely subject to calculations that double and float are designed to do. What would NaN express for a real world number?

Leaving reasons behind it alone, it is what it is and there's nothing we could do about it, so the best route to go is to use nullable types (they are designed to help with exactly this kind of situation). It's the right way to solve this problem. If you don't want to do that (and exceptions don't make sense), you should resort to the magic number solution. If you chose to do so, just make sure it's outside of the domain of valid results.

EDIT (very common misconception about decimal):

As also noted by MSDN, decimal is not fixed point. It is a floating point number:

A decimal number is a floating-point value that consists of a sign, a numeric value where each digit in the value ranges from 0 to 9, and a scaling factor that indicates the position of a floating decimal point that separates the integral and fractional parts of the numeric value.

Comments