我有以下程序:
def main():
print "Running"
primes = sieve(100000)
print "Sieve is done"
def sieve(n):
print "starting sieve"
primes = []
times = 0
numbers = range(2, n):
print "sieve array filled"
while len(numbers) > 0:
current = numbers[0]
primes.append(current)
numbers.remove(current)
times = times + 1
if (times % 10 == 0):
print str(times) + "th prime is " + str(current)
# Remove every multiple
for i in numbers:
if (i % current == 0):
numbers.remove(i)
当找到大量的素数(比如一万个)时,我希望通过查看输出能够看到程序的距离。所以我决定打印每十个素数。但是,当打印出来时,它会一直等到程序的最后才打印出来。我在打印声明之后立即添加了sys.stdout.flush()
,但它没有任何区别。然后我尝试使用python -u <file name>
运行脚本,但仍然没有任何区别。
这是我得到的输出:
Running
starting sieve
sieve array filled
大约一分钟后,其余的输出会立即显示出来。
为什么我不能关闭缓冲区?我试图尽可能少地修改代码。
答案 0 :(得分:3)
测试了一些东西,我不确定你的问题实际上是输出缓冲,它只是算法的行为。尝试在current
循环顶部附近打印while
,您会发现早期数字需要很长时间才能完成,然后随着numbers
变得越来越短, current
的每个新值都可以更快地处理,并且您会开始看到素数弹出。
尝试:
while len(numbers) > 0:
current = numbers[0]
print current
primes.append(current)
numbers.remove(current)
答案 1 :(得分:2)
这个速度太慢的原因是从数字中删除元素的循环:
# Remove every multiple
for i in numbers:
if (i % current == 0):
numbers.remove(i)
每次删除一个数字时,Python都必须移动所有元素,然后将该数字移回一个地方。每次删除都是O(n)*,你做O(n)删除,所以这一步的每次迭代需要O(n ^ 2)次。
如果用列表推导替换它,那么Python将从旧列表中构建一个新列表 - 不涉及移动 - 这是一个O(n)操作。这是我做这一步的方式:
# Remove every multiple
numbers = [i for i in numbers if (i % current) != 0]
通过此更改,您的代码可以更快地以方式运行。它在5秒内完成,并且没有输出缓冲问题。
* Python列表操作here有一个很好的时间复杂表。
答案 2 :(得分:0)
尝试使用sys.stdout.write
代替print
。这应该更适合sys.stdout.flush
。