这是我的VBE(MS Excel 2007 VBA)中的一个小宝石:
?clng(150*0.85)
127
x = 150*0.85
?clng(x)
128
有人可以解释这种行为吗?恕我直言,第一个表达式应该产生128(.5舍入到最接近的偶数),或者至少两个结果都应该相等。
答案 0 :(得分: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/。)
答案 1 :(得分:2)
关于VBA的一个“有趣”的事情是对CInt()等的四舍五入是所谓的银行家四舍五入。银行家舍入是0.5值向上或向下取整的位置,具体取决于数字是偶数,所以2.5轮到2,3.5到4等等。
这里可以找到关于舍入的更多内容
答案 2 :(得分:1)
这是一个猜测,但.85可能无法表示为浮点数。如果它被0.0000000000001关闭,它仍然会以奇怪的方式影响舍入。
如果您使用CDec(.85)强制它进入十进制模式,您就不会觉得奇怪。这是我不使用单/双的众多原因之一,其中准确性很重要。
答案 3 :(得分:1)
我的理论是VBA / VB6使用x87进行浮点计算,如果中间结果为80位,则隐式地将双精度转换为更高的精度。因此,对v
的赋值或使用CDbl
的显式转换将中间80位值转换回64位有效地舍入(或截断它)。
以下是一些讨论:
Extended (80-bit) double floating point in x87, not SSE2 - we don't miss it?
答案 4 :(得分:0)
Kevin和Jonathan所说的都是真的,但Jonathan的回答更适用于此。如果您处理货币类型数字而不是浮点数,那么将应用银行家的舍入规则。