def pyth_triplets(n=1000):
"Version 1"
for x in xrange(1, n):
x2= x*x
for y in xrange(x+1, n):
z2= x2 + y*y
zs= int(z2**.5)
if zs*zs == z2:
yield x, y, zs
>>> print list(pyth_triplets(20))
[(3, 4, 5), (5, 12, 13), (6, 8, 10), (8, 15, 17), (9, 12, 15), (12, 16, 20)]
V.1算法具有单调递增的x
值。
编辑
看来这个问题还没有解决 :)
自从我回来并重新审视了代码后,我尝试了第二种方法,它几乎比我的先前建议快4倍(对于N = 10000,大约占CPU时间的26%),因为它避免了许多不必要的计算:
def pyth_triplets(n=1000):
"Version 2"
for z in xrange(5, n+1):
z2= z*z
x= x2= 1
y= z - 1; y2= y*y
while x < y:
x2_y2= x2 + y2
if x2_y2 == z2:
yield x, y, z
x+= 1; x2= x*x
y-= 1; y2= y*y
elif x2_y2 < z2:
x+= 1; x2= x*x
else:
y-= 1; y2= y*y
>>> print list(pyth_triplets(20))
[(3, 4, 5), (6, 8, 10), (5, 12, 13), (9, 12, 15), (8, 15, 17), (12, 16, 20)]
请注意,此算法具有递增的z值。
如果将该算法转换为C语言,由于乘法比加法需要更多时间,因此可以最小化必要的乘法,考虑到连续平方之间的步骤是:
(x+1)² - x² = (x+1)(x+1) - x² = x² + 2x + 1 - x² = 2x + 1
因此,所有内部的x2= x*x和y2= y*y都将被转换为像这样的加法和减法。
def pyth_triplets(n=1000):
"Version 3"
for z in xrange(5, n+1):
z2= z*z
x= x2= 1
y= z - 1
while x < y:
x2_y2= x2 + y2
if x2_y2 == z2:
yield x, y, z
x+= 1
y-= 1
elif x2_y2 < z2:
x+= 1
else:
y-= 1
当然,在Python中,额外生成的字节码实际上会使算法比版本2慢,但我敢打赌(没有检查 :))V.3在C中更快。
大家加油 :)