在.NET上的双精度问题

10 浏览
0 Comments

在.NET上的双精度问题

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

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

\n它计算出小于或等于\"value\"的最高数字,且是\"step\"的倍数。但是它缺乏精度,如下面的测试所示:\n

[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);
}

\n第一个和第二个断言是正确的,但是第三个断言失败了,因为结果只在小数点后6位相等。为什么会这样?有没有办法可以纠正这个问题?\n更新 如果我调试测试,我会发现值在小数点后8位相等,而不是6位,可能是因为Math.Round引入了一些不精确性。\n注意 在我的测试代码中,我写了\"F\"后缀(显式浮点常量),我本意是\"D\"(双精度),所以如果我更改一下,可以获得更高的精度。

0
0 Comments

Double precision problems on .NET

在.NET平台上的双精度问题

浮点数运算在计算机上并不是精确科学 :).

如果你想要精确到预定义的小数位数,使用Decimal而不是double,或者接受一个较小的间隔。

在IEEE规定的有效数字范围内,它是一门精确的科学。

为了强调上述观点:浮点数是精确的。你想要的数字可能无法表示为IEEE浮点数,这意味着你必须将该数字别名到最接近的一个,从而导致误差,但这并不意味着你可以表示的数字中有错误。

此外,Decimal也可能遇到与Double相同的问题,因为它们也是浮点数。它们可能会遇到相同的表示问题,但这种情况下的错误要少得多,因为它们的基数是10,而不是2,而我们习惯于处理十进制的表示问题(例如,1/3在十进制中是0.333333......)。

解决方法:

1. 使用Decimal类型来处理需要精确小数位数的计算,而不是使用Double类型。

示例代码:

decimal number1 = 0.1m;
decimal number2 = 0.2m;
decimal sum = number1 + number2;
Console.WriteLine(sum); // 输出:0.3
double number3 = 0.1;
double number4 = 0.2;
double sum2 = number3 + number4;
Console.WriteLine(sum2); // 输出:0.30000000000000004

2. 如果必须使用Double类型进行计算,可以通过舍入操作来减少误差。

示例代码:

double number1 = 0.1;
double number2 = 0.2;
double sum = number1 + number2;
double roundedSum = Math.Round(sum, 2);
Console.WriteLine(roundedSum); // 输出:0.3

这样可以将计算结果舍入到指定的小数位数,减少由于浮点数表示不精确而导致的误差。

通过以上两种方法,我们可以在.NET平台上处理双精度问题,并尽量减小计算中的误差。

0
0 Comments

Double precision problems on .NET

在.NET中出现双精度问题的原因是,浮点数(float和double)并不具有无限的精度,因此断言两个浮点数是否相等时,必须包含一个容差。只要你的数字具有合理数量的有效数字,这是可以接受的。

以下是一些使用浮点数(float和double)时需要注意的情况:

- 如果你要对非常大和非常小的数字进行数学运算,请不要使用浮点数。

- 如果你需要无限精度,请不要使用浮点数。

- 如果你要对大量的值进行聚合,请不要使用浮点数(误差会相互累积)。

- 如果你需要速度和大小,请使用浮点数。

浮点数的精度是基于二进制位数而不是十进制位数。因此,浮点数在十进制位数上可能存在精度问题。

整数是一种具有无限精度的类型。在数学运算中,整数不会丢失任何精度。虽然可以实现一个具有无限精度的十进制类型,但在.NET中没有提供该功能。

因此,浮点数的精度问题可以通过使用System.Decimal类型来解决。System.Decimal类型具有无限精度,可以用于需要精确计算的场景。

以上是浮点数在.NET中出现双精度问题的原因以及解决方法的相关内容。如果你想了解更详细的关于精度如何影响数学运算结果的分析,请参考这个回答

注意:本文中的两位参与者之间的对话只是为了说明问题,具体的解决方法和建议应以上述内容为准。

0
0 Comments

(Double precision problems on .NET)

在.NET中,双精度问题是指浮点数(float和double)在进行比较时可能出现的问题。实际上,我有点希望他们没有为浮点数实现“==”操作符。因为几乎总是错误的去问一个double或者float是否等于任何其他值。

是的!是的!是的!我已经说了一段时间了。这就像是整个0.999... = 1.0问题一样。(1.0 - 0.000... = 1.0)。浮点数与整数完全不同。

浮点数在计算机中的表示方式与整数不同,因此在进行比较时会出现一些问题。这是由于浮点数的精度有限,无法精确表示某些小数。因此,当我们使用"=="操作符比较两个浮点数时,可能会得到错误的结果。

解决这个问题的方法是使用特定的比较函数,如Math.Abs方法来比较两个浮点数的差值是否小于某个阈值。这样可以避免直接比较浮点数的精确值。

例如,我们可以使用以下代码来比较两个浮点数的差值是否小于0.0001:

double a = 1.0;

double b = 0.9999;

if (Math.Abs(a - b) < 0.0001)

{

// 两个浮点数相等

}

else

{

// 两个浮点数不相等

}

通过使用这种比较方法,我们可以避免由于浮点数精度问题导致的错误比较结果。这种方法可以在任何使用浮点数比较的情况下都适用,帮助我们正确处理浮点数的相等性判断。

0