使用三个 IF 与使用 IF-ELIF-ELSE:前者更快
Using three IFs vs using IF-ELIF-ELSE: former is faster
我写了一个代码来找到ugly numbers。在尝试使其更快时,我发现使用 3 个 IF 而不是 IF-ELIF-ELSE 可以使我的代码更快。我尝试了 运行 多次迭代 n 的代码,发现大部分时间都是如此。
我觉得 IF-ELIF-ELSE 应该更快,因为如果满足其中一个条件,它就不会进入其他条件。但我无法找到实际发生的任何逻辑。
代码如下:
ugly = [0]*n
ugly[0] = 1
i2, i3, i5 = 0, 0, 0
count = 1
while count<n:
n2 = ugly[i2]*2
n3 = ugly[i3]*3
n5 = ugly[i5]*5
next = min(n2, n3, n5)
if next==n2:
i2 += 1
elif next==n3:
i3 += 1
else:
i5 += 1
if next != ugly[count-1]:
ugly[count] = next
count += 1
您的代码的两个版本计算结果的方式不同,因此它们花费不同的时间不足为奇。
当您使用 if
/elif
/else
时,您通常会多次计算相同的 next
值。例如,六可以计算为 2*3
或 3*2
。由于当 6
是 n2
、n3
、n5
,你最终会选择 i2
在第一遍递增,然后在第二遍选择 i3
,因为 n3
仍然是六。 if next != ugly[count-1]:
检查将防止重复值出现在输出中,但您仍然需要额外 运行 循环体。
当您使用多个if
时,所有生成最小n
值的i
值将同时递增。这意味着您将只计算每个难看的数字一次,即使它可以通过多种不同的方式生成。避免额外的工作意味着代码 运行s 更快。您也可以删除 if next != ugly[count-1]:
保护代码,因为您永远不会重复生成相同的值。
不确定是否能够解释,但在我看来您想要最快的方法和您的代码
- 正在调用
min
执行函数调用 + 循环 + 比较
- 然后它将最小值与 3 个值中的 2 个进行比较
那是 很多 的测试。专门为 3 个值调用 min
是多余的。
我重写了没有 min
的循环(如果值相等,min
returns 最左边的参数,作为 Python 2 的实现细节,现在保证 python 3) 仅使用不等式测试(链接运算符)
while count<n:
n2 = ugly[i2]*2
n3 = ugly[i3]*3
n5 = ugly[i5]*5
if n5 >= n2 <= n3:
next = n2
i2+=1
elif n5 >= n3 <= n2:
next = n3
i3 += 1
else:
next = n5
i5 += 1
# below: not changed
if next != ugly[count-1]:
ugly[count] = next
count += 1
因为只有 3 个数字可以比较,所以这样的测试速度更快。
对于 n=2000000
在我的机器上:
- 你的方法:7.78 秒
- 我的方法:6.32秒
这两种代码当然会产生相同的结果。
请注意,我不会调用我的变量 next
,因为它是一个内置函数
我写了一个代码来找到ugly numbers。在尝试使其更快时,我发现使用 3 个 IF 而不是 IF-ELIF-ELSE 可以使我的代码更快。我尝试了 运行 多次迭代 n 的代码,发现大部分时间都是如此。
我觉得 IF-ELIF-ELSE 应该更快,因为如果满足其中一个条件,它就不会进入其他条件。但我无法找到实际发生的任何逻辑。
代码如下:
ugly = [0]*n
ugly[0] = 1
i2, i3, i5 = 0, 0, 0
count = 1
while count<n:
n2 = ugly[i2]*2
n3 = ugly[i3]*3
n5 = ugly[i5]*5
next = min(n2, n3, n5)
if next==n2:
i2 += 1
elif next==n3:
i3 += 1
else:
i5 += 1
if next != ugly[count-1]:
ugly[count] = next
count += 1
您的代码的两个版本计算结果的方式不同,因此它们花费不同的时间不足为奇。
当您使用 if
/elif
/else
时,您通常会多次计算相同的 next
值。例如,六可以计算为 2*3
或 3*2
。由于当 6
是 n2
、n3
、n5
,你最终会选择 i2
在第一遍递增,然后在第二遍选择 i3
,因为 n3
仍然是六。 if next != ugly[count-1]:
检查将防止重复值出现在输出中,但您仍然需要额外 运行 循环体。
当您使用多个if
时,所有生成最小n
值的i
值将同时递增。这意味着您将只计算每个难看的数字一次,即使它可以通过多种不同的方式生成。避免额外的工作意味着代码 运行s 更快。您也可以删除 if next != ugly[count-1]:
保护代码,因为您永远不会重复生成相同的值。
不确定是否能够解释,但在我看来您想要最快的方法和您的代码
- 正在调用
min
执行函数调用 + 循环 + 比较 - 然后它将最小值与 3 个值中的 2 个进行比较
那是 很多 的测试。专门为 3 个值调用 min
是多余的。
我重写了没有 min
的循环(如果值相等,min
returns 最左边的参数,作为 Python 2 的实现细节,现在保证 python 3) 仅使用不等式测试(链接运算符)
while count<n:
n2 = ugly[i2]*2
n3 = ugly[i3]*3
n5 = ugly[i5]*5
if n5 >= n2 <= n3:
next = n2
i2+=1
elif n5 >= n3 <= n2:
next = n3
i3 += 1
else:
next = n5
i5 += 1
# below: not changed
if next != ugly[count-1]:
ugly[count] = next
count += 1
因为只有 3 个数字可以比较,所以这样的测试速度更快。
对于 n=2000000
在我的机器上:
- 你的方法:7.78 秒
- 我的方法:6.32秒
这两种代码当然会产生相同的结果。
请注意,我不会调用我的变量 next
,因为它是一个内置函数