用布尔值打破嵌套的 while 循环
我的程序是用来寻找毕达哥拉斯三元组的,也就是满足 a^2 + b^2 = c^2
且 a+b+c=1000
的一组数字。程序运行得很顺利,但它在运行的早期就找到了答案,所以我想要在所有的循环中提前退出。我尝试了一个简单的布尔方法,但不知道为什么我的循环在运行了一秒后就停止了。如果我去掉 exit = True
这一行,程序就能正常运行(但显然就无法提前退出了)。
另外,如果我用简单的 0
或 1
来检查这个问题,结果也是一样的。有没有人能告诉我为什么会这样?
i = 0
j = 0
k = 0
exit = False
while (i < 999 and exit == False):
while (j < 999 and exit == False):
while (k < 999 and exit == False):
if i*i + j*j == k*k:
if i + j + k == 1000:
exit = True
ii = i
jj = j
kk = k
k += 1
j += 1
k = 1
i += 1
j = 1
i = 1
print('result: %d^2 + %d^2 = %d^2' % (ii, jj, kk))
5 个回答
0
为什么不直接用一种更符合Python风格的方法来解决这个问题呢:
[(a,b,c) for a,b,c in itertools.product(range(0,999), repeat=3) if (a**2 + b**2 == c**2) and (a + b + c == 1000)]
0
你已经被建议过如何重构代码,以避免一开始就需要中断循环。个人来说,我会使用生成器函数的方式,参考一下@pillmuncher的解决方案(如果你还在考虑使用循环的话)。
这里有一个例子,展示了如何在不使用布尔标志的情况下中断循环:
i = 1
while i < 999:
j = 1
while j < 999:
k = 1
while k < 999:
if i*i + j*j == k*k and i + j + k == 1000:
ii, jj, kk = i, j, k
else:
k += 1
continue
break
else:
j += 1
continue
break
else:
i += 1
continue
break
print('result: %d^2 + %d^2 = %d^2' % (ii, jj, kk))
或者,使用更简洁的 for ... in range(...)
循环(在Python 2中更好用的方式是 xrange
):
for i in range(1, 999):
for j in range(1, 999):
for k in range(1, 999):
if i*i + j*j == k*k and i + j + k == 1000:
ii, jj, kk = i, j, k
else:
continue
break
else:
continue
break
else:
continue
break
print('result: %d^2 + %d^2 = %d^2' % (ii, jj, kk))
1
函数是处理提前退出逻辑的好方法。我还把你的循环改成了使用 xrange()
这个内置函数,这样可以让你的代码看起来更简洁。
def triplet():
for i in xrange(1000):
for j in xrange(1000):
for k in xrange(1000):
if i*i + j*j == k*k:
if i + j + k == 1000:
return (i, j, k)
i, j, k = triplet()
print('result: %d^2 + %d^2 = %d^2' % (i, j, k))
需要注意的是,从这里开始,你可以进行一些优化。
- 比如说,给定
i
和j
后,你只需要测试一个k
,也就是k == 1000 - i - j
。 - 再比如,如果你已经测试过
i == 1
和j == 2
,那么就不需要再测试i == 2
和j == 1
,因为它们的结果是一样的。
另外,如果你想在循环中跳过 0
,可以用 xrange(1, 1000)
。xrange()
让你可以指定一个开始和结束的位置。
2
把它变成一个生成器函数:
>>> def pythagorean_triangles(target):
... for a in range(1, target):
... for b in range(1, target):
... for c in range(1, target):
... if a ** 2 + b ** 2 == c ** 2 and a + b + c == target:
... yield a, b, c
...
>>> triangles = pythagorean_triangles(1000)
>>> next(triangles)
(200, 375, 425)
2
你遇到的具体问题就是,你的代码实际上是符合你设定的标准,当
ii == 0
jj == 500
kk == 500
如果你不想要这个简单的解决方案,你应该在一开始就把值初始化为1
(或者,更好的是,找到这个简单的机会,把重复的部分提取出来,只在一个地方设置,比如j = 1
)。