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 对象库参考。
在标准 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 对象库参考。