一尘不染

.NET上的双精度问题

c#

我有一个简单的C#函数:

public static double Floor(double value, double step)
{
    return Math.Floor(value / step) * step;
}

这将计算出较高的数字,小于或等于“值”,即“ step”的倍数。但是它缺乏精度,如以下测试所示:

[TestMethod()]
public void FloorTest()
{
    int decimals = 6;
    double value = 5F;
    double step = 2F;
    double expected = 4F;
    double actual = Class.Floor(value, step);
    Assert.AreEqual(expected, actual);
    value = -11.5F;
    step = 1.1F;
    expected = -12.1F;
    actual = Class.Floor(value, step);
    Assert.AreEqual(Math.Round(expected, decimals),Math.Round(actual, decimals));
    Assert.AreEqual(expected, actual);
}

第一个和第二个断言都可以,但是第三个断言失败,因为结果只等于小数点后第六位。这是为什么?有什么办法可以纠正这个问题?

更新 如果调试测试,我会发现直到小数点后第8位(而不是第6位)的值都相等,这可能是因为Math.Round引入了一些不准确性。

注意 在我的测试代码中,我写了“ F”后缀(显式浮点常量),我的意思是“ D”(双精度),因此,如果我进行更改,则可以提高精度。


阅读 402

收藏
2020-05-19

共1个答案

一尘不染

如果省略所有F后缀(即-12.1代替-12.1F),则等于将增加几位数。由于,您的常数(尤其是期望值)现在处于浮动状态F。如果您故意这样做,请解释。

但是对于其余部分,我同意其他比较双精度或浮点值是否相等的答案,但这并不可靠。

2020-05-19