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

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

请帮忙!

4

2 回答 2

3

Office 97 和 VBA 对问题的解释同样适用于 Excel 2007。尽管迁移到更高版本,但核心 VBA 系统基本上没有变化,因此困扰旧 VBA 宏的相同类型的准确性问题将持续存在。

根本问题在于以二进制表示小数的固有不准确性,以及如何使用 IEEE 浮点表示至少做出一些努力来减轻这种不准确性。在此位置对 IEEE 表示的主题进行了非常体面的处理。

*编辑:只是一点点额外的细节信息。*

举一个简单的例子来说明这个问题,假设小数表示为 2 的逆幂之和,例如 2 -1、 2 -2、 2 -3等。最终看起来像 0.5、0.25、0.125 等等。如果您准确地代表这些数字,那么一切都很好。但是,考虑像 0.761 这样的数字;2 -1 +2 -2让你达到 0.750,但现在你需要 0.011。2 -3 (.125) 太大了,但 2 -4 (.0625) 太小了……所以你不断地使用较小的 2 次方,意识到你永远无法完全准确地表示数字。

选择变成您停止解决并接受固有的不准确性,因为对于您正在解决/建模的问题“足够好”。

于 2012-10-01T20:36:40.287 回答
1

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

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

相关问题是 Base=2 ,它使 "1,x" 中的 "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)中,并且只使用整数来执行显示功能(通过整数除法及其余数在数学上切掉整数和小数部分)。一种享受,我告诉你……不是。

于 2012-10-01T21:08:02.377 回答