gpt4 book ai didi

VBA:Variant/Double 和 Double 之间的区别

转载 作者:行者123 更新时间:2023-12-04 18:59:11 24 4
gpt4 key购买 nike

我使用的是 Excel 2013。在以下代码片段中,VBA 为 damage 计算 40 :

Dim attack As Variant, defense As Variant, damage As Long
attack = 152 * 0.784637
defense = 133 * 0.784637
damage = Int(0.5 * attack / defense * 70)

如果数据类型改为 Double , VBA 为 damage 计算 39 :
Dim attack As Double, defense As Double, damage As Long
attack = 152 * 0.784637
defense = 133 * 0.784637
damage = Int(0.5 * attack / defense * 70)

在调试器中, Variant/DoubleDouble值看起来相同。然而, Variant/Double似乎有更高的精度。

谁能解释这种行为?

最佳答案

tldr; 如果您需要比 Double 更高的精度,不要使用 Double .

答案在于将结果强制转换为 Double 的时机。来自 Variant .一个 Double是 IEEE 754 浮点数,根据 IEEE 规范,可逆性保证为 15 位有效数字。您的值(value)与该限制有关:

0.5 * (152 * .784637) / (133 * .784637) * 70 = 39.99999999999997 (16 sig. digits)

当 VBA 被强制为 double 时,它会将超过 15 位有效数字的任何内容四舍五入:
Debug.Print CDbl("39.99999999999997") '<--Prints 40

其实你可以 watch VBE 中的这种行为。键入或复制以下代码:
Dim x As Double
x = 39.99999999999997

VBE 通过将文字值转换为 Double 来“自动更正”文字值。 ,这给你:
Dim x As Double
x = 40#

好的,现在您可能会问这与 2 个表达式之间的差异有什么关系。 VBA 使用它可以使用的“最高阶”变量类型来评估数学表达式。

在您的第二个 Sub您将所有变量声明为 Double在右侧,操作以 Double 的高阶进行评估。 ,则结果隐式转换为 Variant在作为 Int() 的参数传递之前.

在您的第一个 Sub你在哪里 Variant声明,隐式转换为 Variant在传递给 Int 之前不执行- 数学表达式中的最高阶是 Variant ,所以 不执行隐式转换 在将结果传递给 Int() 之前- Variant仍然包含原始 IEEE 754 浮点数。

documentationInt :

Both Int and Fix remove the fractional part of number and return the resulting integer value.



不执行舍入。最上面的代码调用 Int(39.99999999999997) .底部代码调用 Int(40) . “答案”取决于您想要舍入的浮点误差级别。如果 15 有效,则 40 是“正确”答案。如果您想对最多 16 位或更多有效数字的任何内容进行分词,那么 39 是“正确”答案。解决方法是使用 Round并明确指定您正在寻找的精度级别。例如,如果您关心完整的 15 位数字:
Int(Round((0.5 * attack / defense * 70), 15))

请记住,您在输入中的任何地方使用的最高精度是 6 位,因此这将是一个合乎逻辑的舍入截止:
Int(Round((0.5 * attack / defense * 70), 6))

关于VBA:Variant/Double 和 Double 之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41928378/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com