2011-06-02 41 views
5

我有一个执行大量使用小数计算的系统,偶尔会加起来相同的号码,但返回不同的结果,+/- 0.000000000000000000000000001另外的十进制顺序会影响结果

下面是一个简单的例子:

decimal a = 2.016879990455473621256359079m; 
decimal b = 0.8401819425625631128956517177m; 
decimal c = 0.4507062854741283043456903406m; 
decimal d = 6.7922317815078349615022988627m; 

decimal result1 = a + b + c + d; 
decimal result2 = a + d + c + b; 

Console.WriteLine((result1 == result2) ? "Same" : "DIFFERENT"); 
Console.WriteLine(result1); 
Console.WriteLine(result2); 

输出:

DIFFERENT 
10.100000000000000000000000000 
10.100000000000000000000000001 

的差异是如此之小,没有什么实际作用,但有没有人看到过类似本b安伏?我期望在合计相同的数字时,您总能得到相同的结果。

+10

这是StackOverflow中最常见的单一问题。 – 2011-06-02 23:11:11

+0

谷歌浮点不精确的表示,阅读它的维基百科或搜索:) – sehe 2011-06-02 23:12:47

+0

值得一提的是'十进制'数据类型应该是免疫的四舍五入错误。 http://msdn.microsoft.com/en-us/library/system.decimal(v=vs.71).aspx – 2011-06-02 23:22:02

回答

7

Numerical analysis的整个领域致力于研究这些效果以及如何避免它们。

为了在汇总浮点数列表时产生最佳结果,首先将列表中的数据从最小到最大排序,然后按照该顺序将它们相加。

+0

由于他使用小数(而不是浮点数),这不是一个不同的问题? – 2011-06-02 23:26:10

+0

@Mark,'decimal'是一个浮点数,但是为尾数分配的位数与指数的位数不同,为处理货币提供了更好的工具。 “double”通常只有14位数字的精度,这就是在足够的尾数的边缘,以表示例如美国的赤字精确到百分之一美元。 “小数”可以代表两倍以上的数字,但是由于指数较小,因此总体范围小得多。 – sarnold 2011-06-02 23:31:06

+0

+1特别是关于排序的位。 :) – sarnold 2011-06-02 23:31:19

2

根据to MSDN,小数的精度为28-29位。您的号码中至少有一位是29位数字,因此您可能会超出限制。

2

您可能会怀疑某个decimal类型可以免受各地使用者的诅咒double

但是because decimal has 28-29 digits of precision并且您的输入是要求29位数字精度的总和,您恰好处于您的数据类型可以精确表示的边缘。

0

由于四舍五入的结果多个数字可能会有所不同,取决于他们的总结顺序。这不会发生在数学上,但在你的例子中计算总和的顺序很重要。 result += number;求和并将结果存储在结果变量中。那时某些精度已经丢失。但是,如果我们按照相同的顺序进行操作,它总会产生相同的结果。

Console.WriteLine(numbers.Sum()); // Always returns 9.214085249270111332166335344 

由于这许多程序使用银行家舍入产生更接近的结果。请知道精度总是丢失。有没有办法来存储compuiter MEMOR

Rounding

Bankers Rounding