Eratosthenes的Python筛不起作用
首先,这是我的家庭作业,我目前正在python上筛选Eratosthenes。 我的程序看起来像:Eratosthenes的Python筛不起作用,python,sieve-of-eratosthenes,sieve,Python,Sieve Of Eratosthenes,Sieve,首先,这是我的家庭作业,我目前正在python上筛选Eratosthenes。 我的程序看起来像: x=[] for i in range(2,100): x.append(i) primes=[] i=2 while len(x)!=0: k=x[0] x.pop(0) primes.append(k) while k*i in x: x.remove(k*i) i+=1 print(primes) p
x=[]
for i in range(2,100):
x.append(i)
primes=[]
i=2
while len(x)!=0:
k=x[0]
x.pop(0)
primes.append(k)
while k*i in x:
x.remove(k*i)
i+=1
print(primes)
print(x)
当我的程序打印“素数”时,我得到:
[2, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39,
41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77,
79, 81, 83, 85, 87, 89, 91, 93, 95, 97, 99]
为什么列表中有复合数字?看来这个计划应该能奏效
#
编辑了程序,现在看起来:
x=[]
for i in range(2,100):
x.append(i)
primes=[]
while len(x)!=0:
i=2
k=x[0]
x.pop(0)
primes.append(k)
while k*i<=max(x):
x.remove(k*i)
i+=1
if k*i not in x:
i+=1
print('primes','\n',primes,sep='')
print('x','\n',x,sep='')
x=[]
对于范围(2100)内的i:
x、 附加(i)
素数=[]
而len(x)=0:
i=2
k=x[0]
x、 流行音乐(0)
素数追加(k)
当k*i时,一个问题是您只会添加到i
。每次从列表中弹出另一个元素时,需要将i
重置回2
也就是说,首先从列表中弹出2。逐渐增加i
以从列表中删除2的所有倍数。在此结束时,i
将为50。但是当你返回并从列表中弹出3时,i
仍然是50,所以它只在列表中查找50*3
即使你修复了这个问题,它仍然无法工作,因为一旦你找到一个不在列表中的值,你就会停止查看i
值。但是有可能k*i
不在列表中,但是k*(i+1)
是——例如,当你把2的倍数乘以后,3的第一个倍数(即6)不在列表中,但下一个倍数(即9)在列表中。因此,除非您尝试列表最大值的每一个倍数,否则您无法停止。一个问题是您只能将其添加到i
。每次从列表中弹出另一个元素时,需要将i
重置回2
也就是说,首先从列表中弹出2。逐渐增加i
以从列表中删除2的所有倍数。在此结束时,i
将为50。但是当你返回并从列表中弹出3时,i
仍然是50,所以它只在列表中查找50*3
即使你修复了这个问题,它仍然无法工作,因为一旦你找到一个不在列表中的值,你就会停止查看i
值。但是有可能k*i
不在列表中,但是k*(i+1)
是——例如,当你把2的倍数乘以后,3的第一个倍数(即6)不在列表中,但下一个倍数(即9)在列表中。因此,在尝试列表最大值之前,您不能停止。注释:
- 应该使用更具描述性的变量名
- 每次进入k*i in x循环时,需要在2处重新启动i
- x、 对于大x,pop(0)速度较慢
- x、 对于大x,移除(k*i)速度较慢
- 应将内部while循环更改为“whilek*i
下面是一个使用位列表的工作快速筛选:
评论:
- 应该使用更具描述性的变量名
- 每次进入k*i in x循环时,需要在2处重新启动i
- x、 对于大x,pop(0)速度较慢
- x、 对于大x,移除(k*i)速度较慢
- 应将内部while循环更改为“whilek*i
下面是一个使用位列表的工作快速筛选:
你应该接受@BrenBarn的答案,因为它涵盖了重要的内容。但这里还有一些提示:
- 有一种更简单、更快的方法来创建初始
x
列表
让Python为您做这件事。只需将range()
包装在list()
中,如下所示:
MAX_NUM = 100
x = list(range(2, MAX_NUM))
以后我们将有更多机会使用MAX_NUM
;继续读下去
- 在Python中,最好使用
for
循环和range()
而不是,同时将循环添加到索引变量中
而不是:
i = 2
while k*i <= max(x):
# do stuff with k*i
i += 1
Python内置的range()
将为您生成一系列值,从k*2
开始,每次添加k
,并以k
的最后倍数(小于max(x)
停止。现在,您的循环运行得更快,并且避免了一系列倍增
- 与索引
x[0]
以获取k
,然后使用x.pop()
放弃x
中的k
值不同,有一种更简单的方法
list.pop()
返回弹出的值。所以你可以在一行中这样做:
k = x.pop()
- 您多次计算
max(x)
。但是您已经知道x
中的最大数字,因为您构建了x
。在构建x
时,您可以在变量中保存最大值,并使用此变量,而不是反复查找max(x)
。max(x)
的好处在于它不会检查已取出的数字;例如,当k
为3时,99将被删除。但是max(x)
非常昂贵,所以我认为仅仅使用保存的值是一个整体的胜利
这就是为什么我保存了MAX\u NUM
。所以你可以这样做:
for i in range(k*2, MAX_NUM, k):
# do stuff with i
for k in range(2, MAX_NUM):
if k not in x:
continue
- 如果您刚刚开始,您可能不知道Python的
set()
类,但它对解决这个问题有好处。正如dstromberg在其回答中所说,x.remove(some_value)
在x
包含许多值时速度较慢。但是从集合中删除值总是一个非常快速的操作
您可以像这样构建一个集合:
x = set(range(2, 100))
此集合将包含2到99(含)之间的所有整数值
然后,关于集合的一个巧妙之处是:使用.discard()
成员函数(使用集合
的另一件便宜的事情),您可以在不检查成员是否在集合中的情况下除去成员
实际上,
中的(用于列表)和list.remove()
都很昂贵。因此,一个集合
将两个昂贵的操作替换为一个便宜的操作
一旦您的原始程序进入工作状态,请保留它的副本,然后将其重写为使用集合
而不是列表
。将最大整数从
# list solution
if i in my_list:
my_list.remove(i)
# set solution
my_set.discard(i)
for k in range(2, MAX_NUM):
if k not in x:
continue
result = list(my_set) # get a list of values stored in my_set
print('primes','\n',primes,sep='')
print('primes')
print(primes)
print('primes:\n{}'.format(primes))