为什么VBA中的for循环在使用万分之一的边界时会少循环一次?
在VBA中处理函数时,我注意到有时在测试过程中,当我使用不同的参数运行同一函数时,会得到不同的结果。我写了下面这篇文章试图弄清楚到底发生了什么 当为什么VBA中的for循环在使用万分之一的边界时会少循环一次?,vba,excel,for-loop,decimal,Vba,Excel,For Loop,Decimal,在VBA中处理函数时,我注意到有时在测试过程中,当我使用不同的参数运行同一函数时,会得到不同的结果。我写了下面这篇文章试图弄清楚到底发生了什么 当for循环以第千位的边界执行时,它会像我预期的那样,在for语句中循环3次。在这里,即时窗口为我慷慨地打印了一个“3”: 但是,当我将边界和步长减小一个量级时,for循环只执行两次for语句 Const vStart = 0.0001 Const vStep = 0.0001 Const vStop = 0.0003 Sub LoopThru()
for循环
以第千位的边界执行时,它会像我预期的那样,在for
语句中循环3次。在这里,即时窗口为我慷慨地打印了一个“3”:
但是,当我将边界和步长减小一个量级时,for循环
只执行两次for
语句
Const vStart = 0.0001
Const vStep = 0.0001
Const vStop = 0.0003
Sub LoopThru()
Dim myVar As Double
Dim counter As Integer
For myVar = vStart To vStop Step vStep
counter = counter + 1
Next myVar
Debug.Print counter
End Sub
在我的实际项目中,我正在创建一个大型3D值数组作为查找表。由于数组的第一个维度必须使用Solver生成,因此我将通过创建此查找表来大大减少应用程序的运行时间,而不必在应用程序运行时反复使用Solver重新计算
因为它是一个3D数组,所以有3个嵌套的for循环,第二个循环的值可能从十万分之一到十分之一不等
也许,
do-while循环
更适合这种情况——事实上,我现在正在重写代码以使用while循环。或循环的条件集。无论是哪种方式,我都想知道这个问题的最佳解决方案,以及为什么执行的循环数会因这些循环
的边界大小而不同。原因是可以存储在浮点变量中的精度有限。
要获得完整的解释,你应该阅读David Goldberg在1991年3月出版的《计算调查》上发表的论文《每个计算机科学家都应该知道的浮点算术》
在VBA中,默认的浮点类型是Double,即IEEE 64位(8字节)浮点数
您需要重构代码,以便在循环计数器中使用整数类型
演示一种转换为整数循环计数器的方法,考虑如下:
Const vStart = 0.0001
Const vStep = 0.0001
Const vStop = 0.0003
Sub LoopThru()
Dim myVar As Double
Dim counter As Long
For counter = 0 To (vStop - vStart) * 10000 Step vStep * 10000
myVar = counter * vStep + vStart
Debug.Print "Iteration " & counter, "myVar = " & myVar
Next
End Sub
您需要如何在更广泛的环境中实施将取决于您的具体情况
既然提到了你在数组上循环,考虑使用像
之类的东西。
For i = LBound(YourArray, n) to UBound(YourArray, n)
其中n
=循环的数组维度如果显式地将常量声明为“Double”,会发生什么?我认为在循环中从隐式初始化类型到双精度类型的强制转换或舍入可能会在某个地方出错。使用for
循环出现问题的原因是浮点精度(或缺少精度)。我需要一个解释。您需要为循环计数器使用Long
类型。@八位专家,我尝试将常量声明为Doubles
,但没有效果@chris,我还试图将循环计数器(myVar
)声明为Long
,但是Long
变量类型是整数,所以我刚刚得到了一个溢出。“帮助”菜单还使我打开了变量类型vbDecimal
,我尝试了该类型,但也没有成功。可能缺少一个包?问题的根源是浮点精度,以及由此产生的舍入。您需要将循环计数器重新设置为Long
更改为其他浮点数据类型并不能解决根本问题。如果你需要这方面的帮助,请在Q中添加更多细节。
For i = LBound(YourArray, n) to UBound(YourArray, n)