I've a double
variable called x
.
In the code, x
gets assigned a value of 0.1
and I check it in an 'if' statement comparing x
and 0.1
if (x==0.1)
{
----
}
Unfortunately it does not enter the if
statement
Should I use
Double
ordouble
?What's the reason behind this? Can you suggest a solution for this?
A cool hack i found is to use the
.GetHashCode()
method which returns an int that represents the double ,i.e.(0.4d + 0.3d + 0.2d + 0.1d).GetHashCode() //returns -1072693248
1d.GetHashCode() //returns 1072693248
so as you noted by now we can use something like this
usage :
AccurateEquality((0.4d + 0.3d + 0.2d + 0.1d),1) //returns true
while :
(0.4d + 0.3d + 0.2d + 0.1d) == 1d //returns false
I tried it on multiple cases and it seems to work well.
Most above ways or following stupid extension method!
Double (called float in some languages) is fraut with problems due to rounding issues, it's good only if you need approximate values.
The Decimal data type does what you want.
For reference decimal and Decimal are the same in .NET C#, as are the double and Double types, they both refer to the same type (decimal and double are very different though, as you've seen).
Beware that the Decimal data type has some costs associated with it, so use it with caution if you're looking at loops etc.
As a general rule:
Double representation is good enough in most cases but can miserably fail in some situations. Use decimal values if you need complete precision (as in financial applications).
Most problems with doubles doesn't come from direct comparison, it use to be a result of the accumulation of several math operations which exponentially disturb the value due to rounding and fractional errors (especially with multiplications and divisions).
Check your logic, if the code is:
it should not fail, it's to simple to fail, if X value is calculated by more complex means or operations it's quite possible the ToString method used by the debugger is using an smart rounding, maybe you can do the same (if that's too risky go back to using decimal):
You need a combination of
Math.Abs
onX-Y
and avalue
to compare with.You can use following Extension method approach
Since you rarely call methods on double except
ToString
I believe its pretty safe extension.Then you can compare
x
andy
likeif(x.Equals4DigitPrecision(y))
Use
decimal
. It doesn't have this "problem".