Using == with double data type

  • Thread starter Thread starter David Hoffer
  • Start date Start date
D

David Hoffer

Does C# have the same problem as C++ with code like this?

if (GetDouble1() == GetDouble2())
{
}

In C++, due to the IEEE storage format, it is possible to have 2 doubles
that are essentially the same value but not quite, so the above code will
not do what you expect. Boost has some extensions to STL to solve this
problem.

Does C# have similar problems? If so, what is the right C# way of handling
this issue?

-dh
 
David,
Does C# have the same problem as C++ with code like this?

if (GetDouble1() == GetDouble2())
{
}

In C++, due to the IEEE storage format, it is possible to have 2 doubles
that are essentially the same value but not quite, so the above code will
not do what you expect. Boost has some extensions to STL to solve this
problem.

Does C# have similar problems? If so, what is the right C# way of handling
this issue?

Yes, floating-point (not just double precision) numbers/arithmethic has this
problem in virtually every language because of the representation that you
have noted. One way of handling this is to calculate the precision of the
machine that your code is running on and then do a comparison to see if the
difference is less than or equal to the precision of the machine. If it is,
then the values are identical as far as you can tell.

Note that C# has the "Decimal" type that can help is many situations.

Regards,

Randy
 
David, Randy,

One could also introduce some "delta" value and consider the values equal if
their difference is smaller than the delta. The delta can obviously be the
machine precision but it can also be bigger.
 
Thanks for the reply, how do I determine the precision of the machine?
Also, since everybody has this problem, is there any code libraries
available (C# extensions) that deal with this? This seems like something
that Microsoft would address...

-dh
 
Check out Double.Epsilon Right now, it's a constant value. Theoretically,
if they port .Net to a different architecture, where the precision is
different, the value of Epsilon will change as well.

You should be able to do something like:

if(Math.Abs(GetDouble1() - GetDouble2()) < Double.Epsilon)
{
// they are "equal" -- sort of
}
 
David,
Thanks for the reply, how do I determine the precision of the machine?
Also, since everybody has this problem, is there any code libraries
available (C# extensions) that deal with this? This seems like something
that Microsoft would address...

See code in books such as Numerical Recipies, Numerical Algorithms in
Smalltalk and Java, etc. Here is a start:

private static System.Int64 radix = 0;
private static System.Double machinePrecision = 0.0D;

private static void ComputeRadix( )
{
System.Double anA = 1.0D, aB = 1.0D, aTemp1, aTemp2;
do
{
anA += anA;
aTemp1 = anA + 1.0D;
aTemp2 = aTemp1 - anA;
}
while( aTemp2 - 1.0D != 0.0D );
while( radix == 0 )
{
aB += aB;
aTemp1 = anA + aB;
radix = ( System.Int64 ) ( aTemp1 - anA );
}
}

private static void ComputeMachinePrecision( )
{
System.Double aFloatingRadix = ComputeRadix( );
System.Double anInverseRadix = 1.0D / aFloatingRadix;
machinePrecision = 1.0D;
System.Double aTempPrecision = 1.0D + machinePrecision;
while( ( aTempPrecision - 1.0D ) != 0.0D )
{
machinePrecision *= anInverseRadix;
aTempPrecision = 1.0D + machinePrecision;
}
}

Note that you may want to compute the precision from the negative side too.

Regards,

Randy
 
David,

By the way, my machine reports the following:

Floating-Point Calculation Parameters:
--------------------------------------
Radix : 2
Machine Precision : 1.11022302462516E-16
Negative Machine Precision : 5.55111512312578E-17
Smallest Number : 4.94065645841247E-324
Largest Number : 1.79769313486232E+308

So any two floating point numbers that are less than 1.11022302462516E-16
apart are essentially equal.

Regards,

Randy
 
Back
Top