当您运行执行导致十进制值的数值计算的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
另外,它并不能解释为什么我以前从未见过它。
请帮忙!
答案 0 :(得分:3)
Office 97和VBA中对问题的解释同样适用于Excel 2007.尽管迁移到更高版本,但核心VBA系统基本没有变化,因此困扰旧版VBA宏的相同类型的精度gremlins将持续存在
根本问题在于二进制中分数表示的固有不准确性,以及如何使用IEEE浮点表示来减轻这种不准确性的至少一些努力。在this location.
对IEEE表示主题进行了非常好的处理* 编辑:只是一小部分细节的额外信息。 *
对于一个非常简单的例子,在一个简单的例子中说明了这个问题,考虑一种情况,其中小数表示为2的反幂的和,例如2 -1 ,2 - 2 ,2 -3 ,依此类推。最终看起来像.5,.25,.125等等。如果你代表完全那些数字,一切都很好。但是,请考虑像.761这样的数字; 2 -1 +2 -2 可以获得.750,但现在需要.011。 2 -3 (。125)太大,但2 -4 (。0625)太小......所以你继续使用2的较小幂,实现你从不完全代表精确的数字。
选择变为你停止解决的地方并接受固有的不准确性,因为你正在解决/建模的问题“足够好”。
答案 1 :(得分: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&LT; i&gt; 是尾数中的位。
尝试使用此表示法获得1,4,并且您击中了精确墙......在二进制权重中没有0.4的有限分解。因此,规范指定你应该在真实数字之前代表数字,这将留下0,39999..9997346(或尾部的任何东西)。
“好”的新闻是,我上周就这个主题烧了四个“c”编码日,如果你使用表示你的号码,你可以不用双打非常小的尺度(比如10 ^ -9),然后存储在非常大的变量(long64)中,并使用除整数之外的任何显示函数(通过数学方式切除积分和小数部分)整数除法及其余数)。一种享受,我告诉你......不是。