“清洁up"双精度值'impreciseness

本文关键字:impreciseness 双精度 quot 清洁 up | 更新日期: 2023-09-27 18:13:03

我有一个从第三方API获取数据的程序,但有时我得到的双精度值以"不精确"(或过于精确)的方式表示,例如。

0.3表示为0.2999999999999

0.04表示为0.03999999999999

这会导致问题,特别是当我想进行相等比较时。是否有一种方法来清理"不精确"的双精度值,因为我收到他们?

我能想到的:

    public Form1()
    {
        InitializeComponent();
        double x = 0.2999999999999; //from third party API          
        x = cleanDouble(x); //x=0.3
    }
    private double cleanDouble(double input)
    {
        string s = input.ToString("0.##########");
        double.TryParse(s, out input);
        return input;
    }

有更有效的方法吗?对我来说,将double类型转换为string类型再转换回double类型似乎不是很高效或优雅。

非常感谢。

注:对于我的应用程序,我将得到的值的精度不会超过0.00000001。

P.P.S.我不会事先知道我将从第三方API获得什么价值。可以是0.000499999999999、0.03999999999999999、100.04999999999999999等。

P.P.P.S.出于这个问题的目的,我需要使用双精度,而不是十进制。

“清洁up"双精度值'impreciseness

您可以不处理这些数字,而编写自己的比较函数。比如:

Bool Test = IsRoughlyEqual(.0001, .0002, .01);
public bool IsRoughlyEqual(double NumA, double NumB, double Tolerance)
{
    double Result = Math.Abs(NumA - NumB);
    if (Result > Tolerance)
        return false;
    else
        return true;
}

我不确定你是如何想出这样的数据的,所以这可能适用,也可能不适用,但是你只使用Math.Round(double, int)是安全的吗?这并不是很优雅,它更像是解决问题的权宜之计。但如果真的没有办法清理你拉进来的东西,那就可以了。

既然你说它不需要超过0.00000001的精确度,你可以只做

Math.Round(value, 8);

这将比将双精度类型转换为字符串然后重新解析为双精度类型快得多。

private double cleanDouble(double input)
{
    double ceil = Math.Ceil(input);
    if (ceil - input < 0.00000001)
        return ceil;
    double floor = Math.Floor(input);
    if (input - floor < 0.00000001)
        return floor;
    return input;
}

请记住,有些数字不能100%精确地用双精度型表示,因此需要一定的容差