为什么CLng会产生不同的结果?
这里有一个小宝石直接从我的VBE(MS Excel 2007中VBA):为什么CLng会产生不同的结果?
?clng(150*0.85)
127
x = 150*0.85
?clng(x)
128
任何人能解释这种现象?恕我直言,第一个表达式应该产生128(.5舍入到最接近的偶数),或者至少应该两个结果相等。
我觉得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/了解更多信息。)
啊关于VBA的一些“有趣”的事情就是CInt()等的四舍五入就是所谓的银行家四舍五入。四舍五入是0.5值取整或取决于数字是否为偶数,2.5轮到2,3.5到4等等。
更可以在这里找到有关舍入
他提到它应该四舍五入到最接近的问题。 – 2011-02-14 08:31:59
在这种情况下,127不是“最接近的偶数”。这没有解释。 – wqw 2011-02-14 13:01:46
这是一个有点猜测,但0.85可能无法表示为一个浮点数。如果它关闭了0.0000000000001,它仍然可能会以奇怪的方式影响舍入。
如果您使用CDec(.85)将其强制为十进制模式,则不会产生奇怪现象。这是为什么我不使用单/双精度很重要的原因之一。
凯文和乔纳森所说的都是真的,但乔纳森的答案在这里更适用。如果您正在处理货币类型的数字而不是浮动点,那么将应用银行家的舍入规则。
我的理论是VBA/VB6使用x87进行浮点计算,如果中间结果为80位,这会隐式地将双精度转换为更高的精度。因此,指定v
或使用CDbl
进行显式转换将中间80位值转换为64位,然后对其进行四舍五入(或截断)。
下面是一些讨论:
Extended (80-bit) double floating point in x87, not SSE2 - we don't miss it?
奇怪。 `CLng(CDbl(150 * 0.85))`修复了它。 `圆形(150 * 0.85)`。 – wqw 2011-02-14 08:28:31
CSng也是如此。我的理论认为这是一个浮点错误。 – 2011-02-14 08:35:11