Excel 2007 VBA 计算错误

3
当您运行执行数字计算的VBA宏得到一个小数值时,返回的结果可能会不正确。
以下是几个示例:
Dim me_wrong as Double
me_wrong = 1000 - 999.59

结果 = 0.409999999999968

Dim me_wrong_too as Double
me_wrong_too = 301.84 - 301

结果 = 0.839999999999975

我以前从未注意到这一点。究竟发生了什么???

我看过关于Office 97的以下文章,但找不到Excel 2007中的任何错误: http://support.microsoft.com/default.aspx?scid=kb;en-us;165373

此外,它并没有解释为什么我以前从未见过它。

请帮帮我!

2个回答

3
Office 97和VBA的问题解释同样适用于Excel 2007。尽管迁移到较新版本,但核心VBA系统基本上没有改变,因此困扰旧版VBA宏的同种准确性难题将会持续存在。
根本问题在于二进制小数表示中固有的不准确性,以及如何通过IEEE浮点表示至少做出一定程度的缓解。关于IEEE表示的主题有一个非常不错的处理方式,可参见此位置。 *编辑:只是一点额外的详细信息。*
举个简单的例子来说明这个问题,在一个小数被表示为二的负幂之和(比如2-1、2-2、2-3等)的情况下,那看起来像是.5、.25、.125等等。如果你精确地表示这些数字,那就没问题了。然而,考虑到一个像.761这样的数字;2-1+2-2可以得到.750,但现在你需要.011。2-3(.125)太大了,但2-4(.0625)又太小了……所以你继续寻找更小的二次幂,意识到你永远无法完全准确地表示这个数字。
问题变成了你何时停止解决并接受固有的不准确性作为你正在解决/建模问题所需的“足够好”的解决方案。

谢谢David,那么我以前是不是很幸运从未发现过这个问题。添加和减去没有受到此问题影响的数字? - Wayne Shelley
不错的文章。这里有一篇直接标题为“Excel中浮点算术可能会产生不准确的结果”的文章http://support.microsoft.com/kb/78113 - Richard Morgan
1
在二进制中表示分数时会出现这种不准确性,并且在加法、减法或任何浮点运算中存在风险。我们需要控制这种不准确性的风险。 - David W
1
如果您可以坚持使用仅限4位小数,VBA中的“货币”数据类型旨在避免这些舍入误差-请参见http://msdn.microsoft.com/en-us/library/gg264338.aspx。 - barrowc

1

很不幸,这不是一个错误。

双重表示遵循固定点表示法,其中尾数是一个数字“1,x”,其中“1”是隐含的。有一个指数和一个符号,这使得在Base 2中的完整表示。

相关问题是Base=2,这使得“x”在“1,x”中成为有限精度(53位)分数二进制。认为x=a52*1/2+a51*1/4+a50*1/8+...+a*1**1/(2^52)+a0*1/(2^53),其中a<i>是尾数中的位。

尝试使用此表示获得1.4,您会遇到精度壁垒...在二进制权重中没有0.4的有限分解。因此,规范指定您应该立即表示实际数字之前的数字,这将使您剩下0.39999..9997346(或者无论尾巴是什么)。

好消息是,上周我在这个问题上浪费了四天的“C”编程时间,如果你使用非常小的比例(如10^-9)表示你的数字,将它们存储在非常大的变量(long64)中,然后只使用整数进行显示功能(通过整数除法和它们的余数数学地切片掉整数和分数部分),你就可以不使用双精度浮点数。我告诉你,这是一次美妙的尝试...但并不容易。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接