2009-07-28 41 views
2

我使用下面的代码段,并在一些神秘的情况下,加入的结果并不像它应该是:添加两个双误给出结果

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负责这个“错误计算”,但我需要弄清楚哪一个。 任何人都可以给我一个提示如何找出我的问题的根源?

+0

我想说这里适用于兼作得好:http://stackoverflow.com/questions/ 1193554 /遇到问题时使用float-in-objective-c/1193607#1193607 – 2009-07-28 12:11:54

+0

问题的根源是由浮点精度的错误设置引起的。有人将浮点精度设置为24位,这会导致计算错误。使用_fpreset或_controlfp(MSVC运行时DLL)可以解决这个问题,但是它仍然是设置这个精度的神秘之处吗? – 2009-07-29 15:10:23

回答

9

双不完全准确,请尝试使用十进制而不是

采用双层的advanteage和漂浮在小数是性能

+1

-1一个`Decimal`怎么能比`Double`提供更好的性能?你的CPU知道如何处理`Singles`和`Doubles`,但是`Decimal`上的所有操作都必须在内存中发生,因为内存速度较慢。 – 2009-07-28 12:25:42

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.SingleSystem.Double类型相关联的舍入误差的情况下使用System.Decimal

话虽这么说,但是,这是不是这里的情况。通过在给定点任意四舍五入数字,你假定这个类型也会在同一个点上圆整,这不是它的工作原理。浮点数被存储到它们的最大表示容量,并且只有达到该阈值时才进行舍入。

0

您正在被舍入和精度问题咬伤。请参阅this。十进制可能会有帮助。有关转换和舍入的详细信息,请转至here

从MSDN:

当转换浮点或双精度到十进制,源值转换为十进制表示,并且如果需要的28位小数后四舍五入到最接近的数字。取决于源值的值,可能会发生以下结果之一:

如果源值太小而不能表示为小数,结果变为零。

如果源值为NaN(非数字),无穷大,或过大而不能表示为小数,一个发生OverflowException异常。

0

问题是,双精度只有15 - 16位(你似乎需要更多的精度在你的例子中),而十进制精度为28 - 29.你怎么转换之间的双精度和十进制?

0

不能代表在精确的二进制系统浮点十进制系统中的每个浮点数,这甚至是没有直接关系的“小”的十进制数是怎么了,有些数字只是不“配合“很好地在基地-2。

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

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

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