Excel电子表格计算的精度与Excel VBA计算不同

时间:2015-10-01 16:55:26

标签: excel-vba variables operators numerical-methods vba

我正在开发一个电子表格,该电子表格对非常小的数字执行计算,大约为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

我不确定如何打击这个。不知怎的,我每次都输了一点。除了I之外,VBA一侧的所有内容都被声明为double类型。

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

我知道差异很小,但我正在做很多操作,他们加起来。此外,我仅限于Excel应用程序。

更新

所以我更多地看了这个,并且我已经将问题缩小到余弦输出和单元格值之间的多重步骤。在excel和Excel VBA版本中,我都可以看到它们都是相同的,但我坚持使用以下

In Excel 
0.999992893893247000000*0.156434465= 1.56433353400222E-01

In Excel VBA 
0.999992893893247000000*0.156434465= 1.56433353359991861557855E-01
谁是对的?

1 个答案:

答案 0 :(得分: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

Precision

  

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"