Comparing double values in C#

2018-12-31 16:04发布

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

  1. Should I use Double or double?

  2. What's the reason behind this? Can you suggest a solution for this?

标签: c# .net double
15条回答
弹指情弦暗扣
2楼-- · 2018-12-31 16:13

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

public static bool AccurateEquality(double first,double second)
{
    return Math.Abs(first.GetHashCode()) == Math.Abs(second.GetHashCode());
}

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.

查看更多
君临天下
3楼-- · 2018-12-31 16:19

Most above ways or following stupid extension method!

public static bool EqualsTo(this double value, double value2)
{
    var bytes1 = BitConverter.GetBytes(value);
    var bytes2 = BitConverter.GetBytes(value2);

    var long1 = BitConverter.ToInt64(bytes1, 0);
    var long2 = BitConverter.ToInt64(bytes2, 0);

    return long1 == long2;
}
查看更多
宁负流年不负卿
4楼-- · 2018-12-31 16:25

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.

查看更多
千与千寻千般痛.
5楼-- · 2018-12-31 16:26

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:

x = 0.1

if (x == 0.1)

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):

if (x.ToString() == "0.1")
查看更多
梦寄多情
6楼-- · 2018-12-31 16:31

You need a combination of Math.Abs on X-Y and a value to compare with.

You can use following Extension method approach

public static class DoubleExtensions
    {
        const double _3 = 0.001;
        const double _4 = 0.0001;
        const double _5 = 0.00001;
        const double _6 = 0.000001;
        const double _7 = 0.0000001;

        public static bool Equals3DigitPrecision(this double left, double right)
        {
            return Math.Abs(left - right) < _3;
        }

        public static bool Equals4DigitPrecision(this double left, double right)
        {
            return Math.Abs(left - right) < _4;
        }

        ...

Since you rarely call methods on double except ToString I believe its pretty safe extension.

Then you can compare x and y like

if(x.Equals4DigitPrecision(y))

查看更多
柔情千种
7楼-- · 2018-12-31 16:31

Use decimal. It doesn't have this "problem".

查看更多
登录 后发表回答