Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用python实现素数_Python_Performance_Loops_Primes - Fatal编程技术网

用python实现素数

用python实现素数,python,performance,loops,primes,Python,Performance,Loops,Primes,我对编程相当陌生,我决定做一些练习来提高我的能力。我一直在做一个练习:“找出200万以下所有素数的总和。”我的代码太慢了 起初,我试图作为一个普通的素数问题来解决,结果是: sum = 2 + 3 for i in range (5, 2000000, 2): for j in range (3, i, 2): if i%j == 0: break else: sum += i print(sum) 这样,所有偶数都将从循

我对编程相当陌生,我决定做一些练习来提高我的能力。我一直在做一个练习:“找出200万以下所有素数的总和。”我的代码太慢了

起初,我试图作为一个普通的素数问题来解决,结果是:

sum = 2 + 3
for i in range (5, 2000000, 2):
    for j in range (3, i, 2):
        if i%j == 0:
            break
    else:
        sum += i
print(sum)
这样,所有偶数都将从循环中排除。但这并没有解决我的问题。这里的震级真的很大

所以我试图理解这段代码发生了什么。我在循环中有一个循环,循环中的循环运行外部循环时间的索引(不完全是这样,因为列表不是从0开始的),对吗?所以,当我试图找到20以下的素数时,它运行外部循环8次,但内部循环60次(我不知道这个数学是否正确,正如我所说,我对编程非常熟悉)。但是当我使用2000000的时候,我总共运行了大约999930012次内部循环,这太疯狂了

我的朋友告诉我关于埃拉托什尼筛的事,我试图创建一个新的代码:

list = [2]
list.extend(range(3, 2000000, 2))
for i in list:
    for j in list:
        if j%i == 0 and j > i:
            list.remove(j)
print(sum(list))
这就是我尝试模拟筛子的结果(忽略偶数有帮助)。它的速度要快得多(使用其他代码,要找到200000以下的素数需要很长时间,使用这个新代码我可以做到),但它不足以在合理的时间内计算2000000000。自从我开始编写代码以来,代码一直在后台运行,但仍然没有任何内容。我不知道这东西循环了多少次,我现在想都想不起来了


我是来寻求帮助的。为什么这么慢?我应该学习/阅读/做些什么来改进我的代码?还有比这个筛子更有效的方法吗?谢谢您抽出时间。

因为
list.remove
是一个
O(n)
操作,您做了很多。你不是在做一个真正的筛子,只是在伪装中进行试飞;您仍在执行在原始代码中执行的所有剩余测试


Eratosthenes筛通常使用一组标志来实现;在最简单的形式中,每个索引对应于相同的数字,并且除了
0
1
之外,所有索引的值最初都是
True
。迭代,当您找到一个
True
值时,您可以将其倍数的所有索引设置为
False
。这意味着工作是顺序加法,而不是乘法,而不是除法(这要昂贵得多)。

你能再解释一下吗?好的,涵盖第一个筛选情况。当你迭代时,你会发现索引2是真的(素数)。此时,您知道2的所有倍数在定义上都不是素数。因此,您可以只从
2*2
循环到
2000000
,通过
2
(例如,使用
范围(p*p,len(标志),p)
),并将标志列表中的条目设置为
False
。不需要大内存移动(甚至不检查不是倍数的标志),不进行乘法或余数测试(并且
xrange
/
range
的加法速度更快).
3
是同一笔交易;该标志仍然为true,因此它是prime,您可以将所有标志从
3*3
设置为
2000000
逐步从
3
设置为
False
(实际上,作为一种优化,除了
2
之外,对于
3
,您可以逐步使用
2*p
,或者
6
,因为偶数值肯定不是素数)。@settifoglio:如果您想要示例,它们不是超优化的(“数组”)通过巧妙地使用
bytearray
),基于字节的版本在速度和性能上都可以得到极大的提高,但它们在算法上明显优于现有版本,应该足以筛选出前2M个素数(使用超优化的代码,您可以轻松地将工作量减少10倍或更多,但在这里只需一两秒钟并不重要)。谢谢您,先生。我一定会尝试您的建议和Rosetta。您所说的非常有意义,非常感谢。