添加两个给出错误结果的双

时间:2009-07-28 11:59:39

标签: c# .net floating-point double addition

我正在使用以下代码,在某些神秘的情况下,添加的结果并不像它应该的那样:

double _west = 9.482935905456543;
double _off = 0.00000093248155508263153;
double _lon = _west + _off;

// check for the expected result
Debug.Assert(_lon == 9.4829368379380981);
// sometimes i get 9.48293685913086 for _lon (which is wrong)

我在我的应用程序中使用了一些本机DLL,我怀疑某些DLL是造成这种“错误计算”的原因,但我需要弄清楚哪一个。 任何人都可以给我一个如何找出问题根源的提示吗?

5 个答案:

答案 0 :(得分:9)

double并不完全准确,请尝试使用十进制代替

使用double和float over decimal的优点是性能

答案 1 :(得分:2)

起初我认为这是一个舍入误差,但实际上你的断言是错误的。尝试添加计算的整个结果,而不需要任意舍入。

试试这个:

using System;

class Program
{
    static void Main()
    {
        double _west = 9.482935905456543;
        double _off = 0.00000093248155508263153;
        double _lon = _west + _off;

        // check for the expected result
        Console.WriteLine(_lon == 9.48293683793809808263153);       
    }
}

将来虽然最好在需要避免通常与System.DecimalSystem.Single类型相关联的舍入错误的情况下使用System.Double

然而,话虽如此,但事实并非如此。通过任意舍入给定点的数字,您假设该类型也将在同一点上舍入,而不是它的工作方式。浮点数存储到它们的最大代表容量,并且只有达到该阈值时才会进行舍入。

答案 2 :(得分:0)

你被四舍五入和精确问题所困扰。见this。十进制可能有所帮助。有关转化和舍入的详细信息,请转到here

来自MSDN:

  

将float或double转换为十进制时,源值将转换为十进制表示形式,并在需要时在第28个小数位后舍入到最接近的数字。根据源值的值,可能会出现以下结果之一:

     

如果源值太小而无法表示为小数,则结果为零。

     

如果源值为NaN(非数字),无穷大或太大而无法表示为小数,则抛出OverflowException。

答案 3 :(得分:0)

问题是Double只有15 - 16位数的精度(在你的例子中你似乎需要更高的精度)而Decimal的精度为28 - 29.你如何在Double和Decimal之间进行转换?

答案 4 :(得分:0)

你不能准确地在二进制系统中用浮点表示十进制系统中的每个浮点数,这甚至与十进制数的“小”数没有直接关系,有些数字只是“不适合”在基地2很好。

在大多数情况下,使用较长的位宽会有所帮助,但并非总是如此。

要以Decimal(128位浮点)精度指定常量,请使用此声明:

decimal _west = 9.482935905456543m;
decimal _off = 0.00000093248155508263153m;
decimal _lon = _west + _off;