Leopold Asperger
Leopold Asperger

Reputation: 1015

Shortest way of checking if Double is "NaN"

When calling Double.IsNaN() with Double.PositiveInfinity as argument, the result is false. This is against my intuition since infinity is not a number. Apparently "NaN" only exists in terms of a constant in .NET, is this described by the IEEE standard or is it a custom implementation detail? Is there a shorter way to check if a Double is "NaN" than:

(Double.IsNaN(d) || Double.IsPositiveInfinity(d) || Double.IsNegativeInfinity(d))

or

(Double.IsNaN(d) || Double.IsInfinity(d))

Upvotes: 68

Views: 75400

Answers (5)

Adam
Adam

Reputation: 612

In the end, all you are looking at is the bit value of the double. The IEEE standard 754, used by double, states:

  • Positive Infinity has all Exponent bits set, all Significand bits not set, and Sign bit not set.
  • Negative Infinity has all Exponent bits set, all Significand bits not set, and Sign bit set.
  • Nan has all Exponent bits set and at least one Significand bit set. Sign bit can be set or not set. In C#, the constant double.NaN has the Sign bit and most significant Significand bit set.

Therefore, if you don't want to use built-in functions, you can simply check if all Exponent bits are set yourself. You can do this in one of two ways, use unsafe code to extract long value of double or use BitConverter.DoubleToInt64Bits, then check Exponent bits.

public unsafe static bool IsNaNorInfinity(double d)
{
    return (*(long*)(&d) & 0x7FF0000000000000L) == 0x7FF0000000000000L;
}
public static bool IsNaNorInfinity(double d)
{
    return (BitConverter.DoubleToInt64Bits(d) & 0x7FF0000000000000L) == 0x7FF0000000000000L;
}

Upvotes: 1

Prince Owen
Prince Owen

Reputation: 1505

If you'd like the value of double to always be a number, you could use this FiniteOrDefault extension. It is of course inspired by Sergey Berezovskiy's answer.

public static bool HasValue(this double value)
{
    return !double.IsNaN(value) && !double.IsInfinity(value);
}

/// <summary>
/// Returns zero when double is NaN or Infinte
/// </summary>
public static double FiniteOrDefault(this double value)
{
    return value.HasValue() ? value : default;
}

With that, code like the following can be much more readable:

Rect dimensions = new Rect
{
    X = Canvas.GetLeft(Control).FiniteOrDefault(),
    Y = Canvas.GetTop(Control).FiniteOrDefault(),
    Width = Control.ActualWidth.FiniteOrDefault(),
    Height = Control.ActualHeight.FiniteOrDefault()
};

Upvotes: 5

Roman Marusyk
Roman Marusyk

Reputation: 24569

You no longer need an extension from SergeyBerezovskiy answer.

double has IsFinite() method to check if a double is a finite number (is not NaN or Infinity):

double.IsFinite(d)

See source code in .Net Framework and .Net Core

Upvotes: 20

Tony Vitabile
Tony Vitabile

Reputation: 8594

There are three special values in the Double type, which is based on IEEE standard 754. One is Positive Infinity, another is Negative Infinity, and the last is Not-a-Number (NaN). All that the Double.IsNaN method does is check to see if the value in the variable is this special NaN value.

Upvotes: 4

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236208

As MSDN says, NaN means that result is undefined. With infinities result is defined:

A method or operator returns NaN when the result of an operation is undefined. For example, the result of dividing zero by zero is NaN, as the following example shows. (But note that dividing a non-zero number by zero returns either PositiveInfinity or NegativeInfinity, depending on the sign of the divisor.)

So, it's not good idea to tread infinities as NaN. You can write extension method to check if value is not NaN or infinity:

// Or IsNanOrInfinity
public static bool HasValue(this double value)
{
    return !Double.IsNaN(value) && !Double.IsInfinity(value);
}

Upvotes: 83

Related Questions