Leon Husmann
Leon Husmann

Reputation: 684

C# Compare two double with .Equals()

I use ReShaper and when I compare two double values with ==, it suggests that I should use the Math. ABS method with a tolerance. See: https://www.jetbrains.com/help/resharper/2016.2/CompareOfFloatsByEqualityOperator.html

This example

double d = 0.0;
double d2 = 0.0;
if (d == d2)
{
    /* some code */
}

is then converted to

double d = 0.0;
double d2 = 0.0;
if (Math.Abs(d - d2) < TOLERANCE)
{
    /* some code */
}

But I think it's really complicated for a developer to think about the right tolerance. So I thought this may be implemented in the Double.Equals() method.

But this method is implemented like so

public override bool Equals(Object obj) {
    if (!(obj is Double)) { 
        return false;
    } 
    double temp = ((Double)obj).m_value; 
    // This code below is written this way for performance reasons i.e the != and == check is intentional.
    if (temp == m_value) { 
        return true;
    }
    return IsNaN(temp) && IsNaN(m_value);
}

public bool Equals(Double obj)
{ 
    if (obj == m_value) {
        return true; 
    } 
    return IsNaN(obj) && IsNaN(m_value);
}

Why is that? And what is the correct way to compare double values?

Upvotes: 9

Views: 16012

Answers (3)

YUu
YUu

Reputation: 79

https://learn.microsoft.com/en-us/dotnet/api/system.numerics.complex.equals?view=net-6.0

If the obj parameter is not a Complex object, but it is a data type for which an implicit conversion is defined, the Equals(Object) method converts obj to a Complex object whose real part is equal to the value of obj and whose imaginary part is equal to zero before it performs the comparison. The following example illustrates this by finding that a complex number and a double-precision floating-point value are equal.

double n1 = 16.33;
System.Numerics.Complex c1 =
new System.Numerics.Complex(16.33, 0);
Console.WriteLine(c1.Equals(n1));               // Returns true.

Upvotes: 0

fantagons
fantagons

Reputation: 19

I ended up using

double piConstant = 3.142;
double piFractional = 7/22;
if(piConstatnt.String("{0:0.00}")==piFractional.String("{0:0.00}")
{
    // some code
}

This lets me control the precision by setting the desired string format. https://www.csharp-examples.net/string-format-double/

In case you want more info on Equals method from microsoft. https://learn.microsoft.com/en-us/dotnet/api/system.double.equals?view=net-5.0

Upvotes: -2

Pepernoot
Pepernoot

Reputation: 3609

You could create an extension method

public static class DoubleExtension 
{
    public static bool AlmostEqualTo(this double value1, double value2)
    {
        return Math.Abs(value1 - value2) < 0.0000001; 
    }
}

And use it like this

doubleValue.AlmostEqualTo(doubleValue2)

Upvotes: 13

Related Questions