C#Math.Ceiling bug与否?

时间:2010-07-01 14:20:06

标签: c# ceiling

我不知道为什么Ceiling的行为如下图所示

为什么是processingFee!= Settings.PaymentProcessingFeeInPercentage * prizesSum?

View image at full size

alt text http://img514.imageshack.us/img514/3950/csharpceilingproblem.png

7 个答案:

答案 0 :(得分:25)

您的百分比实际上 0.05。这是 close 到0.05的值...并且可能略高于0.05。因此,当它乘以2600时,你得到一个超过130.0的值...然后被“天花板”到131.0。

使用我之前写过的一个小工具(可从this page获得关于.NET二进制浮点类型的信息),看起来最接近0.05的实际float值是0.0500000007450580596923828125。对于双打,它是0.05000000000000000277555756156289135105907917022705078125。

故事的道德:不要将float用于此类事情 - 请使用decimal。或者,如果您只是想表示一个百分比,如果实际只能精确到百分之一,那么使用0-100的整数值。

答案 1 :(得分:4)

这是所涉及数字的浮点表示的结果。 See the wikipedia。可能0.05有一个无限的基数2表示为double,因此Math.Ceiling实际看到的值可能略大于130.

答案 2 :(得分:2)

你看到浮点不精确 0.05的实际base-2表示比0.05稍微多一点,因此产品比130.0稍微多一点。
因此,Math.Ceiling正在逐步推进。

将您的floatdouble更改为decimal

答案 3 :(得分:1)

这是由于当数字以十进制表示时,浮点数的内部存储格式固有地不精确。 Stack Overflow上有很多很多问题。

您返回的数字可能类似于130.000000000000001,因为计算中的数字不能完全表示为二进制浮点数。

答案 4 :(得分:1)

恕我直言,这可能与浮点精度有关。换句话说,2600×0.05给出130.0000 ... 001而不是130。

如果您尝试先将结果四舍五入,而不是致电Math.Ceiling

,该怎么办?

答案 5 :(得分:0)

在我的编译器中,当我查找乘法值时,它表示130.00000193715096,所以math.ceiling结果没问题。问题是浮点数据类型的精度有限。

如果可能,请尝试使用'double'。

答案 6 :(得分:0)

如果您在大型银行业务中使用浮点数,请不要让我将钱存入您的银行。使用小数或最小公分母的整数,即分数。

但是,如果您假设计算量有多大,则可以使用Math.Round来帮助您使用doublefloat。即:

double processingFee = Math.Ceiling( Math.Round( 
    Settings.PaymentProcessingFeeInPercentage * prizesSum, 2 ) );