An Efficient Sieve of Eratosthenes in Python
#Python中的这段非常短而简单的代码尝试针对前N个自然数模拟" Eratosthenes筛",其约束为(0)脚本简短; (1)最小化" if语句"和" for / while循环"; (2)就CPU时间而言的效率。
1 2 3 4 5 6 7 | import numpy as np N = 10**5 a = np.array(range(3,N,2)) for j in range(0, int(round(np.sqrt(N),0))): a[(a!=a[j]) & (a%a[j] == 0)] = 0 a = a[a!=0] a = [2]+list(a) |
在Intel Core I5上,它返回第一个中的质数:
- N = 100,000在0.03秒内;
- N = 1,000,000在0.63秒内;
- N = 2,000,000秒内10,000,000。
在上述限制内,有人愿意在CPU时间方面共享更有效的代码吗?
实际的Eratosthenes NumPy筛子如下所示:
1 2 3 4 5 6 7 8 9 | def sieve(n): flags = numpy.ones(n, dtype=bool) flags[0] = flags[1] = False for i in range(2, n): # We could use a lower upper bound for this loop, but I don't want to bother with # getting the rounding right on the sqrt handling. if flags[i]: flags[i*i::i] = False return numpy.flatnonzero(flags) |
它维护"可能为素数"标志的数组,并直接取消设置与素数倍数相对应的标志,而无需测试可除性,尤其是对于不能被当前正被素数整除的数字。
您正在做的是试算除法,即您只需要测试一下数字是否可被候选除数整除。 即便是良好的试验划分实施,也需要比筛分更多的操作和更昂贵的操作。 您的实现所要做的工作甚至更多,这是因为它考虑了非素数候选除数,并且因为它一直在对其本应知道是质数的数字执行除数测试。