计算中间表达式时,Python嵌套循环速度比较出乎意料地慢

时间:2019-05-13 22:47:05

标签: python algorithm timing

在python执行更多操作的情况下,它会变慢。

以下是两个单独的嵌套循环的非常简单的比较(用于找到总计为1000的勾股三重(a,b,c)):

#Takes 9 Seconds
for a in range(1, 1000):
  for b in range(a, 1000):
    ab = 1000 - (a + b)
    for c in range(ab, 1000):
      if(((a + b + c) == 1000) and ((a**2) + (b**2) == (c**2))):
        print(a,b,c)
        exit()


#Solution B
#Takes 7 Seconds
for a in range(1, 1000):
  for b in range(a, 1000):
    for c in range(b, 1000):
      if(((a + b + c) == 1000) and ((a**2) + (b**2) == (c**2))):
        print(a,b,c)
        exit()

我希望解决方案A可以比解决方案B节省一到两秒,但是相反,它增加了完成时间。两秒钟。

instead of iterating
1, 1, 1
1, 1, 2
...
1, 1, 999
1, 2, 2

It would iterate
1, 1, 998
1, 1, 999
1, 2, 997
1, 2, 998
1, 2, 999
1, 3, 996

在我看来,解决方案a应该通过减少数千至数百万次的操作来极大地提高速度,但实际上并非如此。

我知道有一种大大改进此算法的简单方法,但我试图理解为什么在看起来更快的情况下python的运行速度会变慢。

3 个答案:

答案 0 :(得分:2)

您可以只计算每个解决方案中的迭代总数,然后看到A需要更多的迭代才能找到结果:

#Takes 9 Seconds
def A():
 count = 0
 for a in range(1, 1000):
  for b in range(a, 1000):
    ab = 1000 - (a + b)
    for c in range(ab, 1000):
      count += 1
      if(((a + b + c) == 1000) and ((a**2) + (b**2) == (c**2))):
        print(a,b,c)
        print('A:', count)
        return


#Solution B
#Takes 7 Seconds
def B():
 count = 0
 for a in range(1, 1000):
  for b in range(a, 1000):
    for c in range(b, 1000):
      count += 1
      if(((a + b + c) == 1000) and ((a**2) + (b**2) == (c**2))):
        print(a,b,c)
        print('B:', count)
        return

A()
B()

输出:

A: 115425626
B: 81137726

这就是为什么A较慢的原因。此外,ab = 1000 - (a + b)也需要时间。

答案 1 :(得分:1)

您有两个错误的前提:

  • 方法找到所有三元组。他们不;每个人都会找到一个三元组,然后中止。
  • 上部方法(也称为“解决方案A”)进行的比较较少。

我添加了一些基本的工具来测试您的房屋:

导入时间

#Takes 9 Seconds
count = 0
start = time.time()
for a in range(1, 1000):
  for b in range(a, 1000):
    ab = 1000 - (a + b)
    for c in range(ab, 1000):
      count += 1
      if(((a + b + c) == 1000) and ((a**2) + (b**2) == (c**2))):
        print(a,b,c)
        print(count, time.time() - start)
        break


#Solution B
#Takes 7 Seconds
count = 0
start = time.time()
for a in range(1, 1000):
  for b in range(a, 1000):
    for c in range(b, 1000):
      count += 1
      if(((a + b + c) == 1000) and ((a**2) + (b**2) == (c**2))):
        print(a,b,c)
        print(count, time.time() - start)
        break

输出:

200 375 425
115425626 37.674554109573364
200 375 425
81137726 25.986871480941772

Solution B认为三元组较少。此练习的数学值...是较低的值b1000-a-b吗?

答案 2 :(得分:-1)

是的,性能有所不同,但是因为您的代码在做不同的事情:

  • 解决方案A在range(1000-(a+b), 1000)上运行c,这将更短。 (实际上,它不需要运行c,只需要检查一个值c = 1000-(a+b),因为这是给定a,b满足约束(a + b + c) == 1000)的唯一c值)
    • 但是它确实会计算并存储ab = 1000-(a+b),并将其存储在locals()字典中
  • 解决方案B在整个range(b, 1000)上运行c。但是它只是直接使用表达式1000-(a+b),不会将其存储到局部变量ab