Excel工作表和VBA INT(LOG())函数之间的不一致

时间:2015-01-15 00:21:48

标签: excel-vba int worksheet-function logarithm vba

在标准的 Excel VBA 代码模块中,我创建了自定义公式MyLog10()以获得10个基数的对数:

Public Function MyLog10(ByVal dbl_Input As Double) As Double
    MyLog10 = Log(dbl_Input) / Log(10)
End Function

测试值1000并得到准确的结果3.令人惊讶的是,当Int() VBA函数应用于MyLog10()的结果时,它显示为2.同样的观察结果与Fix() VBA函数(参见以下测试Sub):

Sub TestIntMyLog10()
    Debug.Print MyLog10(1000) 'Result 3 (accurate)
    Debug.Print Int(MyLog10(1000)) 'Result 2  (inaccurate)
    Debug.Print Fix(MyLog10(1000)) 'Result 2  (inaccurate)
End Sub

更令人惊讶的是,我的自定义函数MyLog10(1000)在Excel工作表中输入为=MyLog10(1000)=INT(MyLog10(1000))在两种情况下都返回正确的结果3。

对此VBA /工作表不一致的任何解释(可能是错误)?


此外,通过向自定义VBA MyLog10()的输出添加一个非常小的数字(1E-12),在两种情况下都生成了正确的结果(有/无额外Int()):

Debug.Print Int (Log10(1000)+1E-12) 'Result 3 (accurate)

2 个答案:

答案 0 :(得分:2)

尝试多种类型转换后,找到了解决方案:它使用Decimal类型作为自定义日志函数MyLog10Decimal返回类型。以下是包含通用VBA解决方案并测试Sub TestIntMyLog10()

的代码段
' SOLUTION: using output type decimal : Int() and Fix() return correct value
Public Function MyLog10Decimal(ByVal dbl_Input As Double) As Variant
    MyLog10Decimal = CDec(Log(dbl_Input) / Log(10))
End Function

'Problem: using output type double: Int() and Fix() may return incorrect
Public Function MyLog10(ByVal dbl_Input As Double) As Double
     MyLog10 = Log(dbl_Input) / Log(10)
End Function

Sub TestIntMyLog10()
   ' ** test sample: input number 1000
   'using Log output type double: Int() and Fix() produces incorrect results
    Debug.Print MyLog10(1000) 'Result 3 (accurate)
    Debug.Print Int(MyLog10(1000)) 'Result 2  (inaccurate)
    Debug.Print Fix(MyLog10(1000)) 'Result 2  (inaccurate)

    'using Log output type decimal: Int() and Fix() produces correct results
    Debug.Print Int(MyLog10Decimal(1000)) 'Result 3  (accurate)
    Debug.Print Int(MyLog10Decimal(1000)) 'Result 3  (accurate)
    Debug.Print Fix(MyLog10Decimal(1000)) 'Result 3  (accurate)

   ' ** test sample: input number 0.001
   'using Log output type double: Fix() produces incorrect results
    Debug.Print MyLog10(0.001) 'Result -3 (accurate)
    Debug.Print Int(MyLog10(0.001)) 'Result -3  (accurate)
    Debug.Print Fix(MyLog10(0.001)) 'Result -2  (inaccurate)

    'using Log output type decimal: Int() and Fix() produces correct results
    Debug.Print Int(MyLog10Decimal(0.001)) 'Result -3  (accurate)
    Debug.Print Int(MyLog10Decimal(0.001)) 'Result -3  (accurate)
    Debug.Print Fix(MyLog10Decimal(0.001)) 'Result -3  (accurate)
End Sub

一点解释。 VBA不支持Decimal类型作为Function参数/输出,因此它被声明为应用了CDec转换的Variant。到目前为止,它已经在多个输入(> 1和< 1)上进行了测试并返回了正确的结果。此外,Excel Worksheet包含内置函数LOG10(),但VBA不包含。因此,此VBA解决方案可以在其他Office应用程序中使用,而无需Excel对象库引用。

答案 1 :(得分:1)

你可以在excel中使用= LOG10来获得相同的效果,而不必自己动手(我有Excel 2013,我不确定旧版本是否有这个公式)。

如果您在VBA中需要该公式,则可以使用Application.WorksheetFunction.Log10(数字或变量名称)

我知道这并没有真正回答你的问题,但它是一个可靠的解决办法