令人惊讶的嵌套循环持续时间

时间:2014-10-08 16:16:34

标签: excel excel-vba vba

我的VBA代码中有内部和外部循环。我认为总的执行时间可以估计为外循环计数*内循环计数,但它似乎并非如此,因为执行10 * 10 ^ 8操作大约需要5秒,但执行10 ^ 8 * 10操作大约需要24秒。与内循环的许多重复相比,外循环的许多重复似乎使总执行时间更长,尽管在两个示例中操作的总计数保持相同。它应该像这样工作吗?这是为什么?我做错了吗?

Sub test()
Dim i As Long
Dim j As Long
Dim t As Single

maxI = 0 '1
maxJ = 9 '1 bilion

Do While maxJ >= 0

    t = Timer
    For i = 1 To 10 ^ maxI
    For j = 1 To 10 ^ maxJ
    Next j
    Next i

    Debug.Print maxI + maxJ & " " & maxI & " " & maxJ & " " & Timer - t

    maxI = maxI + 1
    maxJ = maxJ - 1
Loop

End Sub

结果数据集以外部循环中的bilion重复开始,内部循环中重复一次,如下所示:

+-------------------+-----------------+-----------------+----------+
| total_operations  | outer_loop_cnt  | inner_loop_cnt  |   time   |
+-------------------+-----------------+-----------------+----------+
|                9  |              9  |              0  | 222,2305 |
|                9  |              8  |              1  | 24,52734 |
|                9  |              7  |              2  | 8,300781 |
|                9  |              6  |              3  | 5,683594 |
|                9  |              5  |              4  | 5,070313 |
|                9  |              4  |              5  | 5,109375 |
|                9  |              3  |              6  | 5,167969 |
|                9  |              2  |              7  | 4,933594 |
|                9  |              1  |              8  | 4,898438 |
|                9  |              0  |              9  | 5,109375 |
+-------------------+-----------------+-----------------+----------+

结果数据集以内部循环中的bilion重复开始,外部循环中重复一次,如下所示:

+---+---+---+----------+
| 9 | 0 | 9 | 4,800781 |
| 9 | 1 | 8 | 4,890625 |
| 9 | 2 | 7 | 4,808594 |
| 9 | 3 | 6 | 4,800781 |
| 9 | 4 | 5 | 4,757813 |
| 9 | 5 | 4 | 4,972656 |
| 9 | 6 | 3 | 5,308594 |
| 9 | 7 | 2 | 6,980469 |
| 9 | 8 | 1 | 24,54297 |
| 9 | 9 | 0 | 222,3828 |
+---+---+---+----------+

更新:如果我改变代码,那么每个循环都不会像这样计算上限:

Do While maxJ >= 0

    upper_i = 10 ^ maxI
    upper_j = 10 ^ maxJ
    t = Timer
    For i = 1 To upper_i
    For j = 1 To upper_j
    ...

对于更大的外环,我得到更好的结果。但它似乎仍然是真的,最好有几乎相同的内部和外部循环运行计数,以获得最佳性能。对我来说,这仍然令人惊讶。有什么想法吗?

9 9 0 60,07031
9 8 1 14,8125
9 7 2 10,36719
9 6 3 9,414063
9 5 4 9,507813
9 4 5 9,40625
9 3 6 9,523438
9 2 7 9,835938
9 1 8 12,875
9 0 9 11,02344

9 0 9 9,75
9 1 8 9,257813
9 2 7 9,265625
9 3 6 9,273438
9 4 5 9,1875
9 5 4 9,164063
9 6 3 9,21875
9 7 2 10,42969
9 8 1 14,96094
9 9 0 59,66406

顺便说一句,我该如何进行表格格式化?

1 个答案:

答案 0 :(得分:2)

是的,这是有道理的。 For循环边界总是在循环开始时计算。因此,如果你运行内循环十亿次,你计算10 ^ maxI一次,然后10 ^ maxJ一次,然后十亿次重复j = j + 1.如果你运行外循环十亿时间,你曾经10 ^ maxI一次,10 ^ maxJj = j + 1十亿次。