Excel + VBA 与货币格式之间的精度问题

Posted

技术标签:

【中文标题】Excel + VBA 与货币格式之间的精度问题【英文标题】:Precision issues between Excel + VBA with currency formats 【发布时间】:2019-07-30 10:25:13 【问题描述】:

我有一个用户定义函数 (UDF),它接受两个输入。两个输入都被声明为类型Double。但是,虽然输入具有大量小数位数,但一旦传递给 UDF,小数位数就会被截断。

奇怪的是,我似乎无法在干净的工作簿中重现这种行为(即,我想知道这个特定的工作簿是否有什么问题......)。

(简化的)UDF 如下。

Function Wage(HourlyWage As Double, HoursWorked As Double) As Double

    Wage = HourlyWage

End Function

以及正在发生的事情的屏幕截图。

编辑栏显示 UDF 调用。它将 C 列和 D 列作为输入。 HourlyWage 在 C 列中为 25.30364372+,但一旦传递给 UDF 工资,尽管声明为类型 Double,但 HourlyWage 被截断为 25.30360000。

我了解浮点精度的一般要点,但这肯定同样适用于 C 列中的输入和 UDF 一样(实际上,C 列实际上是另一个 UDF 的输出,它已被声明为类型 @ 987654329@)。

Why can't decimal numbers be represented exactly in binary?

Why are floating point numbers inaccurate?

有关 EXCEL 工作簿的其他信息。

我使用的是 Windows 7 Professional 和 Microsoft Office 365 ProPlus 64 位版本。 工作簿是 .xlsb 格式。我还保存为 .xlsm,但无法解决问题。 我无法在干净的工作簿中重现。 工作簿包含大量相互关联的用户定义函数(可能有 40 个) 工作簿包含 11 个工作表。其中 5 个是带有许多参数的数据表,但我不会在总体方案中说大(大约 100 行和 30 列)。 3 张纸有大量的 UDF 和计算(同样,100 行可能 40-50 列) 我不会说工作簿很大。它是 369Kb (.xlsb) 和 525KB (.xlsm) 但是,当输入参数发生更改时,重新计算工作簿的时间出乎意料地长(比如大约 10 秒,我觉得这很令人惊讶,因为从总体上看,计算量并不大)

关于如何解决这个问题的任何想法?精度的损失给我带来了问题......

【问题讨论】:

我无法复制它。我使用您的 UDF 代码得到 25.30364372 作为输出。 您的工作簿中是否有事件触发的宏正在对 E 列进行舍入? @brb Debug.Print [C6], [E6]的结果是什么,只是为了确保没有奇数格式。 如果您的计算涉及数据类型为 Currency 的任何 VBA 变量,那么这些变量在小数点右侧最多只能有 4 位数字 - 请参阅 here 这似乎与您的行为相匹配正在看 谢谢大家的帮助,尤其是@barrowc - 这是货币格式的问题。我会写下答案来帮助别人,但如果你想写下答案或重新粘贴我的答案,我会接受你的版本。 【参考方案1】:

这个答案基于上面的 barrowc 和 Peh 的 cmets。谢谢你们的帮助。

货币数据类型最多有 4 个小数点 (https://docs.microsoft.com/en-gb/office/vba/language/reference/user-interface-help/currency-data-type)。

C 列已使用自定义货币格式进行格式化。输入 VBA UDF 函数时,尽管变量在 UDF 中声明为 Double 类型,但小数点后第 4 位的小数点会被截断。

更改数字格式可以解决问题,如下图所示。

这可以使用 Debug.Print 进行验证

Sub brb()
    Debug.Print [C6], [E6]
    Debug.Print [C8], [E8]
End Sub

【讨论】:

以上是关于Excel + VBA 与货币格式之间的精度问题的主要内容,如果未能解决你的问题,请参考以下文章

VBA 中的 HTML - 无法将单元格格式化为数字/货币

ASP中有啥函数把文本型值转换为数值型值?

excel日期格式与vba中的不同

格式货币 Excel

excel的宏与VBA入门——基础入门

Excel VBA 条件格式与函数