如何正确比较两个x有效双打

时间:2018-06-25 13:56:30

标签: c# compare double

这不是重复的问题。问题中有答案。希望能对您有所帮助。

有两个doubles,其值与小数点相同。

(对不起,这不是一个好案例。因为有时它会返回false,但我找不到该案例。如果您尝试这种情况,则可能没有任何问题。所以不要浪费时间进行测试。)

double a = 0.70448;
double b = 0.70441;

我只想将它们与小数点后4位进行比较。

我具有此帮助程序功能,可以先将它们四舍五入至小数点后四位。

public static double RoundDown(this double value, int decimals)
{
    var multiplier = Math.Pow(10, decimals);
    return Math.Floor(value * multiplier) / multiplier;
}

然后我要检查a是否大于b,如下所示: RoundDown(a, 4) > RoundDown(b, 4)

有时,即使它们看起来相等,有时也会返回true。我非常了解这是一个浮动的问题,所以我想知道是否有任何优雅的解决方案可以将它们进行比较。

更新

我尝试将其乘以整数进行比较。但是,对于此解决方案,我需要处理double infinity和NAN。

    private static CompareResult Compare(double a, double b, double decimals = 0)
    {
        var multiplier = Math.Pow(10, decimals);
        var aInt = Convert.ToInt32(a * multiplier);
        var bInt = Convert.ToInt32(b * multiplier);
        return aInt > bInt ? CompareResult.Greater : aInt < bInt ? CompareResult.Less : CompareResult.Equal;
    }

    private enum CompareResult
    {
        Greater,
        Less,
        Equal
    }
如果double中的一个大于int max或infinity,则抛出

System.OverflowException。另外,这不是优雅比较双精度方式。

重要

我不会舍入x个有效数字。我已经在我的问题中提供了此解决方案,我的问题是:即使四舍五入到x个有效数字,比较它们也将返回true。

再次

我没有找到一种方法来将双精度数舍入或截断为x个有效数字。我在这方面没有问题。

答案

感谢@ m88回答。但这仍然不能解决我的问题。 我终于使用sigma解决了这个问题。 (参考:http://forums.codeguru.com/showthread.php?506300-float-double-value-comparison-significant-figures。)

由于某些人误解了问题,并将其投票作为重复的问题。我无法将答案发布给其他面临相同问题的人。因此,我将答案发布在我的问题中。我希望它可以帮助其他人。

public static int CompareTo(this double value1, double value2, int decimals)
{
    var diff = value1 - value2;
    var sigma = Math.Pow(10, -decimals - 1);
    return Math.Abs(diff) < sigma ? 0 : diff > 0 ? 1 : -1;
}

2 个答案:

答案 0 :(得分:1)

如果您使用Math.Round方法将ab舍入到小数点后四位,a0.7045)将始终大于{{1 }}(b):

0.7044

如果要截断值,则需要注意以下事实:并非所有分数都可以在const double a = 0.70448; const double b = 0.70441; if (Math.Round(a, 4) > Math.Round(b, 4)) ... 中准确表示。如果要“精确”截断,可以考虑将double值转换为double,截断string,然后将截断的string值转换回{{1 }}。像这样:

string

用法:

double

很明显,如果您不希望像在聊天中所说的那样出现任何“浮动问题”,则不能使用浮点数据类型。

答案 1 :(得分:0)

您要截断而不是舍入:

double a = Math.Truncate(100 * 0.70448) / 100;
double b = Math.Truncate(100 * 0.70441) / 100;

if (a > b)
{
    // ...
}

请注意,根据@ mm8的注释,分数不能准确地表示在double中。