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

Inconsistency between Excel Worksheet and VBA INT(LOG()) Functions

在标准 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 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)) 在这两种情况下 returns 的正确结果为 3 .

对这个 VBA/Worksheet 不一致(可能是错误)有什么解释吗?


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

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

您可以在 excel 中使用 =LOG10 来获得相同的效果,而无需创建您自己的函数(我有 Excel 2013,我不确定旧版本是否有该公式).

如果您需要VBA中的那个公式,您可以只使用Application.WorksheetFunction.Log10(数字或变量名称)

我知道这并不能真正回答您的问题,但它是一个可靠的解决方法

尝试了多种类型转换后,找到解决方案:使用Decimal类型作为自定义日志函数MyLog10Decimal return类型。以下是包含通用 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 parameter/output,因此它被声明为应用了 CDec 转换的 Variant。到目前为止,它已经在多个输入(>1 和 <1)上进行了测试,并且得到了 return 的正确结果。此外,Excel 工作表包含一个内置函数 LOG10(),但 VBA 没有。因此,此 VBA 解决方案可在其他 Office 应用程序中使用,无需 Excel 对象库参考。