Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

double.NaN - how does this counterintuitive feature work?

Tags:

double

nan

I stumbled upon .NET's definition of double.NaN in code:

public const double NaN = (double)0.0 / (double)0.0;

This is done similarly in PositiveInfinity and NegativeInfinity.

double.IsNaN (with removing a few #pragmas and comments) is defined as:

[Pure] 
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
public static bool IsNaN(double d) 
{
    if (d != d)
    { 
        return true; 
    }
    else 
    {
        return false;
    }
}

This is very counter-intuitive to me.

Why is NaN defined as division by zero? How is 0.0 / 0.0 represented "behind the scenes"? How can division by 0 be possible in double, and why does NaN != NaN?

like image 330
GeReV Avatar asked Feb 26 '23 12:02

GeReV


2 Answers

Fairly simple answer here. .Net framework has implemented the floating point standard specified by the IEEE (System.Double complies with the IEC 60559:1989 (IEEE 754) standard for binary floating-point arithmetic.). This is because floating point arithmetic actually has to work across many systems, not just x86/64 architectures, so by following the conventions this ensures that there will be less compatibility issues (for instance porting code from a DSP into an x86 processor).

As for the d != d, this is a performance optimisation. Basically this instruction relies on a hardware instruction which can very quickly determine if two double floating point numbers are equal. Under the standard, NAN != NAN and therefore is the fastest way to test. Trying to find a reference for you.

like image 115
Spence Avatar answered Mar 25 '23 02:03

Spence


Why is NaN defined as division by zero? How can division by 0 be possible in double, and why does NaN != NaN?

All of these are mandated by the IEEE 754 standard, which pretty much all modern CPUs implement.

How is 0.0 / 0.0 represented "behind the scenes"?

By having an exponent with all bits set to 1 and a mantissa with at least one bit set to 1. Note that this means that there are a large number of different bit patterns that all represent NaN - but, as mentioned above, even if the bit patterns are identical, they must be considered not equal (i.e. == must return false).

like image 28
Michael Borgwardt Avatar answered Mar 25 '23 02:03

Michael Borgwardt