10

我不知道为什么天花板的行为如下图所示

为什么 processingFee != Settings.PaymentProcessingFeeInPercentage * PrizesSum ?

以全尺寸查看图像

替代文字 http://img514.imageshack.us/img514/3950/csharpceilingproblem.png

4

7 回答 7

25

Your percentage isn't actually 0.05. It's a value close to 0.05... and probably a little bit more than 0.05. Thus when it's multiplied by 2600, you're getting a value just over 130.0... which is then being "ceilinged" to 131.0.

Using a little tool I wrote a while ago (available from this page about .NET binary floating point types) it looks like the actual float value closest to 0.05 is 0.0500000007450580596923828125. For doubles, it's 0.05000000000000000277555756156289135105907917022705078125.

Moral of the story: don't use float for this sort of thing - use decimal. Or if you're just trying to represent a percentage, if it's okay to actually be only accurate to one percent, use an integer value 0-100.

于 2010-07-01T14:24:42.843 回答
4

这是所涉及数字的浮点表示的结果。请参阅维基百科。可能 0.05 具有无限基数 2 表示为双精度,因此 Math.Ceiling 实际看到的值可能略大于 130。

于 2010-07-01T14:23:13.110 回答
2

您会看到浮点不精确。
的实际 base-2 表示0.05略多于0.05,因此乘积略多于130.0
因此,Math.Ceiling正在四舍五入。

float将您的 s 和doubles更改为decimal

于 2010-07-01T14:23:55.450 回答
1

这是因为当数字以十进制表示时,浮点数的内部存储格式本质上是不精确的。Stack Overflow 上有很多很多关于此的问题。

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

于 2010-07-01T14:24:26.307 回答
1

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

如果您尝试先对结果进行四舍五入,而不是 callMath.Ceiling怎么办?

于 2010-07-01T14:24:36.070 回答
0

In my compiler, when i lookup the multiply value, it says 130.00000193715096, so the math.ceiling result is ok. The problem is the limited precision of the float data type.

Try using 'double' instead, if it is possible.

于 2010-07-01T14:26:11.747 回答
0

If you use floating point numbers in a large banking operation, don't let me float my money in your bank. Use decimals, or integers of the least common denominator, i.e. cents.

You could however, use a Math.Round, to help you use doubles or floats, if you make assumptions about how large your calculations will get. i.e.:

double processingFee = Math.Ceiling( Math.Round( 
    Settings.PaymentProcessingFeeInPercentage * prizesSum, 2 ) );
于 2010-07-01T14:26:50.017 回答