我有一个填充了随机数的列表,我想从此列表中返回素数。所以我创建了这些函数:
0889632e a938b990 1e8b2f79 832e26bd 11280868 2a22d676 275ca4b8 10954ef9
和
def is_prime(number):
for i in range(2, int(sqrt(number)) + 1):
if number % i == 0:
return False
return number > 1
但我想提高性能,那么我该如何实现呢?
答案 0 :(得分:5)
Sieve of Eratosthenes,在我的设备上使用PyPy 3.5的1000万以下的素数大约需要0.17秒:
from array import array
def primes(upper):
numbers = array('B', [1]) * (upper + 1)
for i in range(2, int(upper ** 0.5) + 1):
if numbers[i]:
low_multiple = i * i
numbers[low_multiple:upper + 1:i] = array('B', [0]) * ((upper - low_multiple) // i + 1)
return {i for i, x in enumerate(numbers) if i >= 2 and x}
和过滤功能:
filter_primes = primes(10_000_000).intersection
答案 1 :(得分:3)
这个怎么样?我觉得它好一点:
def filter_primes(general_list):
return filter(is_prime, set(general_list))
这样我们就不会多次拨打is_prime()
相同的号码。
答案 2 :(得分:3)
使用基数2,7和61的3轮Miller-Rabin检验(https://en.wikipedia.org/wiki/Miller%2dRabin_primality_test)已知能准确检测所有素数<= 32位,即任何适合python的素数{ {1}}。
如果数字可能很大,这比试验分割或筛分要快得多。
如果数字不能很大(即,你在评论中建议的<10,000,000),那么你可能想要预先计算所有素数的集合&lt; 10,000,000,但有超过600,000。
答案 3 :(得分:2)
Eratosthenes的Sieve比您正在使用的方法Trial Division更有效。
您的试用分组循环可以提高效率,大约一半时间。两个是唯一的素数,所以将两个视为一个特例,之后只处理奇数,这将使工作减半。
我的Python不存在,但这个伪代码应该清楚明白:
def isPrime(num)
// Low numbers.
if (num <= 1)
return false
end if
// Even numbers
if (num % 2 == 0)
return (num == 2) // 2 is the only even prime.
end if
// Odd numbers
for (i = 3 to sqrt(num) + 1 step 2)
if (num % i == 0)
return false
end if
end for
// If we reach here, num is prime.
return true;
end def
step 2
循环中的for
是工作的一半。早先消除了所有偶数,你只需要用奇数试验除数进行测试:3,5,7,......
答案 4 :(得分:1)
def primes_list(num_list):
divs = [2,3,5,7]
primes = [x for x in set(num_list) if 0 not in {1 if ((x%i != 0) | (x in divs)) & (x > 0) else 0 for i in divs}]
return primes
对于此功能,它需要一个列表num_list
作为参数。 divs
是一个预定义的,或者说是硬编码的小于10的质数列表(不包括1)。然后,我们使用列表推导为素数过滤num_list
作为变量primes
。>