2011-02-14 64 views
9

这里有一个小宝石直接从我的VBE(MS Excel 2007中VBA):为什么CLng会产生不同的结果?

?clng(150*0.85) 
127 
x = 150*0.85 
?clng(x) 
128 

任何人能解释这种现象?恕我直言,第一个表达式应该产生128(.5舍入到最接近的偶数),或者至少应该两个结果相等。

+1

奇怪。 `CLng(CDbl(150 * 0.85))`修复了它。 `圆形(150 * 0.85)`。 – wqw 2011-02-14 08:28:31

+0

CSng也是如此。我的理论认为这是一个浮点错误。 – 2011-02-14 08:35:11

回答

11

我觉得wqw是正确的,但我会给出详细情况。

在声明clng(150 * 0.85)150 * 0.85计算在扩展精度:

150 = 1.001011 x 2^7 

在双精度0.85 =

1.1011001100110011001100110011001100110011001100110011 x 2^-1 

乘这些手工,你会得到

1.1111110111111111111111111111111111111111111111111111110001 x 2^6 = 
127.4999999999999966693309261245303787291049957275390625 

这是59位,这很适合在分机截至精度。它小于127.5如此圆润。

在声明x = 150 * 0.85,该59位值四舍五入到53位,给

1.1111111 x 2^6 = 1111111.1 = 127.5 

因此,根据轮半到甚至四舍五入。

(请参阅我的文章http://www.exploringbinary.com/when-doubles-dont-behave-like-doubles/了解更多信息。)

2

啊关于VBA的一些“有趣”的事情就是CInt()等的四舍五入就是所谓的银行家四舍五入。四舍五入是0.5值取整或取决于数字是否为偶数,2.5轮到2,3.5到4等等。

更可以在这里找到有关舍入

http://www.consultdmw.com/rounding-numbers.htm

+0

他提到它应该四舍五入到最接近的问题。 – 2011-02-14 08:31:59

+0

在这种情况下,127不是“最接近的偶数”。这没有解释。 – wqw 2011-02-14 13:01:46

1

这是一个有点猜测,但0.85可能无法表示为一个浮点数。如果它关闭了0.0000000000001,它仍然可能会以奇怪的方式影响舍入。

如果您使用CDec(.85)将其强制为十进制模式,则不会产生奇怪现象。这是为什么我不使用单/双精度很重要的原因之一。

0

凯文和乔纳森所说的都是真的,但乔纳森的答案在这里更适用。如果您正在处理货币类型的数字而不是浮动点,那么将应用银行家的舍入规则。

相关问题