c# NaN comparison differences between Equals() and ==

I found an article addressing your question: .NET Security Blog: Why == and the Equals Method Return Different Results for Floating Point Values

According to IEC 60559:1989, two
floating point numbers with values of
NaN are never equal. However,
according to the specification for the
System.Object::Equals method, it’s
desirable to override this method to
provide value equality semantics.
[…]

So now we have two conflicting ideas
of what Equals should mean.
Object::Equals says that the BCL value
types should override to provide value
equality, and IEC 60559 says that NaN
does not equal NaN. Partition I of
the ECMA spec provides resolution for
this conflict by making a note about
this specific case in section 8.2.5.2 [below]


Update: The full text of section 8.2.5 from the CLI spec (ECMA-335) sheds some more light on this. I’ve copied the relevant bits here:

8.2.5 Identity and equality of values

There are two binary operators defined
on all pairs of values: identity and
equality. They return a Boolean result, and are mathematical
equivalence operators; that is, they are:

  • Reflexive – a op a is true.
  • Symmetric – a op b is true if and only if b op a is true.
  • Transitive – if a op b is true and b op c is true, then a op c is
    true.

In addition, while identity always
implies equality, the reverse is not
true. […]

8.2.5.1 Identity

The identity operator is defined by the CTS as follows.

  • If the values have different exact types, then they are not identical.
  • Otherwise, if their exact type is a value type, then they are identical if
    and only if the bit sequences of the
    values are the same, bit by bit.
  • Otherwise, if their exact type is a reference type, then they are
    identical if and only if the locations
    of the values are the same.

Identity is implemented on System.Object via the ReferenceEquals method.

8.2.5.2 Equality

For value types, the equality operator
is part of the definition of the exact
type. Definitions of equality should
obey the following rules:

  • Equality should be an equivalence operator, as defined above.
  • Identity should imply equality, as stated earlier.
  • If either (or both) operand is a boxed value, […]

Equality is implemented on
System.Object via the Equals
method.

[Note: Although two floating point
NaNs are defined by IEC 60559:1989 to
always compare as unequal, the
contract for System.Object.Equals
requires that overrides must satisfy
the requirements for an equivalence
operator. Therefore,
System.Double.Equals and
System.Single.Equals return True
when comparing two NaNs, while the
equality operator returns False in
that case, as required by the IEC
standard. end note]

The above does not specify the properties of the == operator at all (except for the final note); it is primarily defining the behavior of ReferenceEquals and Equals. For the behavior of the == operator, the C# language spec (ECMA-334) (section 14.9.2) is clear about how to treat NaN values:

If either operand [to operator ==] is NaN, the result is false

Leave a Comment