【问题标题】:Precision of Excel Spreadsheet Calculation different from Excel VBA CalculationExcel电子表格计算的精度不同于Excel VBA计算
【发布时间】:2015-10-01 16:55:26
【问题描述】:

我正在处理一个电子表格,该电子表格对非常小的数字执行计算,大约为 1E-14。我有一个利用电子表格的流程草稿,并且不在 VBA 变量中存储任何数据。我不喜欢这种方法,并希望将幕后的整个过程带入 VBA。

我注意到我无法让这两种方法匹配。相同的操作不同的结果。我正在使用 Excel 2013

An example in a cell 
=B42*COS(2*PI()*E$41*A42) 

or if I plug in values taking all figures reported i get the following 
0.156434465*Cos(2*3.14159265358979*0.012*0.05) 

this results in 
1.56433353400222E-01

如果我在 VBA 中做同样的事情

gsum = Round(data(i + 1, 1), 10) * Cos(2 * pi * Freq * i * dt)

or 
0.156434465*Cos(2*3.14159265358979*0.012*1*0.05) 
i get a different answer 
Watch:Round(data(i + 1, 1), 10) * Cos(2 * Pi * Freq * i * dt):    
0.156433353359992 : Variant/Double : Calculation.realFT

我不知道如何解决这个问题。不知怎的,我每次都输一点。 VBA 端的所有内容都声明为 double 类型,除了 I。

关于如何让 VBA 匹配电子表格精度的任何想法?

我知道差异很小,但我做了很多操作,它们加起来。我也仅限于应用程序的 Excel。

更新

因此,我对此进行了更多研究,并将问题缩小到余弦输出和单元格值之间的乘法步骤。在 excel 和 Excel VBA 版本中,我可以看到它们都是相同的,但我坚持以下

In Excel 
0.999992893893247000000*0.156434465= 1.56433353400222E-01

In Excel VBA 
0.999992893893247000000*0.156434465= 1.56433353359991861557855E-01

谁是对的?

【问题讨论】:

  • Excel 的余弦值可能优于 VBA 的余弦值。 VBA 很旧(自 1990 年代后期以来没有变化),但 Excel 本身一直在不断更新。也可能是 32 位与 64 位的问题。
  • @JohnColeman 嗯,看来 VBA 不会让我使用工作表函数 ala WorksheetFunction.Cos。无论如何围绕这个?
  • 认为 Application.Evaluate("0.156434465*Cos(2*3.14159265358979*0.012*1*0.05)") 将使用 Excel 的 cos()(而不是 VBA)。但是——在我的情况下(Excel 2010)我无法检测到 VBA 和表达式的 Excel 评估之间的任何差异——它们都返回 0.156433353359992。 Charles Williams 是高精度 Excel VBA 方面的专家。您可能会喜欢他的博客:fastexcel.wordpress.com。这也很酷:newtonexcelbach.wordpress.com
  • Application.Evaluate 给了我 VBA 答案,也许是相同的途径?如果将这两个值放在两个单元格中并将它们相乘,那么我会得到另一个值。 2010 年也是这样吗
  • Python 可以在保持精度的同时将长整数相乘。我在 Python 中做了这个乘法 999992893893247*156434465 与结果 156433353359991861557855,表明 VBA 是正确的。顺便说一句,VBA 给出了 24 位精度,表示 55 个二进制位!

标签: excel variables operators numerical-methods vba


【解决方案1】:

一些建议

将变量类型从 double 更改为货币或小数(变体)或字符串

双字节:8 字节

-1.79769313486232e+308 to -4.94065645841247E-324 for negative values
 4.94065645841247E-324 to  1.79769313486232e+308 for positive values

货币:8字节

-922,337,203,685,477.5808 to 922,337,203,685,477.5807

十进制:12字节(声明为Variant,然后使用转换函数CDec)

+/- 79,228,162,514,264,337,593,543,950,335 if no decimal is use
+/-  7.9228162514264337593543950335 (28 decimal places)

了解如何将范围内的数据提取到 VBA:

Public Sub showData()
    Const NL As String = vbCrLf & vbCrLf & vbTab
    Const FR As String = "0.156434465 * Cos(2 * 3.14159265358979 * 0.012 * 0.05)"

    Dim v1 As Variant, v2 As Variant, v3 As Variant, v4 As Variant, v5 As Variant

    v1 = CDec((1 / 3) + (1 / 3) + (1.00059999999977E-03))
    v2 = CDec(CDec(1 / 3) + CDec(1 / 3) + CDec(1.00059999999977E-03))
    v3 = 0.156434465 * Cos(2 * 3.14159265358979 * 0.012 * 0.05)
    v4 = CDec(0.156434465 * Cos(2 * 3.14159265358979 * 0.012 * 0.05))
    v5 = CDec(CDec(0.156434465) * CDec(Cos(CDec(2 * 3.14159265358979 * 0.012 * 0.05))))

    With ActiveSheet.Cells(1, 1)
        MsgBox "Formula: " & vbTab & .Formula & NL & _
                "Text:   " & vbTab & .Text & NL & _
                "Value:  " & vbTab & .Value & NL & _
                "Value2: " & vbTab & .Value2 & vbCrLf & NL & _
                "VBA 1:  " & vbTab & v1 & NL & _
                "VBA 2:  " & vbTab & v2 & vbCrLf & vbCrLf & vbCrLf & _
                "Formula:  " & vbTab & FR & NL & _
                "VBA 3:  " & vbTab & v3 & NL & _
                "VBA 4:  " & vbTab & v4 & NL & _
                "VBA 5:  " & vbTab & v5, , "Precision"
    End With
End Sub


Number precision: 15 digits

Largest allowed positive number: 1.79769313486231E+308

Largest allowed negative number: -1E-307

Smallest allowed negative number: -2.2251E-308

Smallest allowed positive number: 2.229E-308


更多关于this link中.Text .Value 和.Value2 的区别的信息

如果您不使用日期或货币,请确保使用 .Value2(“原始”数据)

参考MS文章“Floating-point arithmetic may give inaccurate results in Excel

【讨论】:

  • 新的数据类型增加了更多的 sigfigs 但仍然关闭。电子表格是否有可能是错误的,或者 Excel 进行数学运算的方式在两者之间是否不同
  • 你可能会发现Floating-point arithmetic很有用
猜你喜欢
  • 1970-01-01
  • 2018-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-25
  • 1970-01-01
  • 2023-01-30
  • 1970-01-01
相关资源
最近更新 更多