Excel精英培训网

 找回密码
 注册
数据透视表40+个常用小技巧,让你一次学会!
查看: 19393|回复: 8

[已解决]vba for循环步长问题

[复制链接]
匿名  发表于 2014-11-17 16:38 |阅读模式
这是在自定义一个函数的时候发现的一个问题,整理了下,如下:
Public Function mihe1(num_1 As Variant, num_2 As Variant) As Variant
Dim i As Variant
mihe1 = 0
For i = num_1 To num_2 Step 0.1
mihe1 = i
Next i
End Function

上面这个步长是0.1,当输入参数为:mihe1(1,2.2)时候,结果只能得到2.1,也就是说循环只计算到了2.1就停止了。
但是当把步长改为0.01或者0.2的时候,却发现最后能得到2.2,也就是循环计算到了2.2.
求大神指导这是为什么。。。
最佳答案
2014-11-18 09:51
本帖最后由 香川群子 于 2014-11-18 10:09 编辑

楼主你要知道循环终止的原理:
当循环计数器的值 i 大于循环计数终点值 i2 时就立即停止。
因此实际循环计数器的最大值 t 应该是<=循环计数终点值 i2 ……所以你提出的现象是很正常的啦。

按如下代码测试:
  1. Sub test()
  2.     Debug.Print fortest(1, 2.2, 0.1)
  3.     Debug.Print fortest(1, 2.2, 0.2)
  4.     Debug.Print fortest(1, 2.2, 0.01)
  5. End Sub
  6. Function fortest(i1, i2, s)
  7.     For i = i1 To i2 Step s
  8.         t = i
  9.     Next
  10.     fortest = vbCr & "Step: " & s & vbCr & "End i=t: " & t & vbCr & "Stop i>i2: " & i & vbCr & "i-i2 diff: " & i - i2
  11. End Function
复制代码
即,固定循环计数起点 1、循环计数终点2.2时,而改变循环步长时,实际效果如下:

Step: 0.1
End i=t:   2.1000000000000008
Stop i>i2: 2.200000000000000888178419700125
i-i2 diff: 8.88178419700125E-16

Step: 0.2
End i=t: 2.199999999999999555810790140037 约等于 2.2
Stop i>i2: 2.4
i-i2 diff: 0.2

Step: 0.01
End i=t: 2.1999999999999964472863211995 约等于 2.2
Stop i>i2: 2.21999999999999623
i-i2 diff: 9.99999999999623E-03

严格上说,步长0.2和步长0.01时,循环计数结果 i 也没有达到2.2,而是无限接近而已。

总之,是小数减法的浮点误差造成的结果。

excel精英培训的微信平台,每天都会发送excel学习教程和资料。扫一扫明天就可以收到新教程
发表于 2014-11-17 16:46 | 显示全部楼层
Public Function mihe1(num_1 As long, num_2 As long) As Variant
Dim i As long
mihe1 = 0
For i = num_1*10 To num_2 *10
mihe1 = i/10
Next i
End Function
回复

使用道具 举报

匿名  发表于 2014-11-17 16:57
qh8600 发表于 2014-11-17 16:46
Public Function mihe1(num_1 As long, num_2 As long) As Variant
Dim i As long
mihe1 = 0

我知道这个是可以得到想要的结果,只是这是为什么啊,哥,能给说下原因么
回复

使用道具

发表于 2014-11-17 17:33 | 显示全部楼层
QQ_5DD8F4 发表于 2014-11-17 16:57
我知道这个是可以得到想要的结果,只是这是为什么啊,哥,能给说下原因么

截断误差吧,步长好像不能用小数
回复

使用道具 举报

发表于 2014-11-17 21:17 | 显示全部楼层
循环的步长可以是正数、负数,可以是整数、可以是小数。只是最好别为0,为0则必须另加结束循环的东东,否则是死循环

楼主的这个问题又是计算机对小数的表示问题:绝大多数小数都不能精确表示。
如MsgBox 0.4 - 2 / 5 = 0 显示为false
mihe1(1,2.2000001)这样在尾巴上加一个很小很小的数,可得到2.2(这个2.2也只是个近似值,蛋痛的小数
回复

使用道具 举报

发表于 2014-11-18 09:51 | 显示全部楼层    本楼为最佳答案   
本帖最后由 香川群子 于 2014-11-18 10:09 编辑

楼主你要知道循环终止的原理:
当循环计数器的值 i 大于循环计数终点值 i2 时就立即停止。
因此实际循环计数器的最大值 t 应该是<=循环计数终点值 i2 ……所以你提出的现象是很正常的啦。

按如下代码测试:
  1. Sub test()
  2.     Debug.Print fortest(1, 2.2, 0.1)
  3.     Debug.Print fortest(1, 2.2, 0.2)
  4.     Debug.Print fortest(1, 2.2, 0.01)
  5. End Sub
  6. Function fortest(i1, i2, s)
  7.     For i = i1 To i2 Step s
  8.         t = i
  9.     Next
  10.     fortest = vbCr & "Step: " & s & vbCr & "End i=t: " & t & vbCr & "Stop i>i2: " & i & vbCr & "i-i2 diff: " & i - i2
  11. End Function
复制代码
即,固定循环计数起点 1、循环计数终点2.2时,而改变循环步长时,实际效果如下:

Step: 0.1
End i=t:   2.1000000000000008
Stop i>i2: 2.200000000000000888178419700125
i-i2 diff: 8.88178419700125E-16

Step: 0.2
End i=t: 2.199999999999999555810790140037 约等于 2.2
Stop i>i2: 2.4
i-i2 diff: 0.2

Step: 0.01
End i=t: 2.1999999999999964472863211995 约等于 2.2
Stop i>i2: 2.21999999999999623
i-i2 diff: 9.99999999999623E-03

严格上说,步长0.2和步长0.01时,循环计数结果 i 也没有达到2.2,而是无限接近而已。

总之,是小数减法的浮点误差造成的结果。

回复

使用道具 举报

匿名  发表于 2014-11-18 09:59
香川群子 发表于 2014-11-18 09:51
楼主你要知道循环终止的原理:
当循环计数器的值 i 大于循环计数终点值 i2 时就立即停止。
因此实际循环计 ...

懂了,谢谢{:11:}
回复

使用道具

匿名  发表于 2014-11-18 09:59
上清宫主 发表于 2014-11-17 21:17
循环的步长可以是正数、负数,可以是整数、可以是小数。只是最好别为0,为0则必须另加结束循环的东东,否则 ...

懂了,谢谢{:11:}
回复

使用道具

发表于 2014-11-18 10:14 | 显示全部楼层
楼主如果需要确保循环计数终止值被包括在循环过程内,那么过程应该这样设置:

    For i = i1 To i2 + s / 2 Step s
        t = i
    Next
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|Excel精英培训 ( 豫ICP备11015029号 )

GMT+8, 2024-4-20 08:53 , Processed in 0.453579 second(s), 11 queries , Gzip On, Yac On.

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表