从Python中的随机数列表中过滤素数的最有效方法

时间:2017-07-02 14:14:01

标签: python algorithm performance python-3.x primes

我有一个填充了随机数的列表,我想从此列表中返回素数。所以我创建了这些函数:

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

但我想提高性能,那么我该如何实现呢?

5 个答案:

答案 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)

  1. Eratosthenes的Sieve比您正在使用的方法Trial Division更有效。

  2. 您的试用分组循环可以提高效率,大约一半时间。两个是唯一的素数,所以将两个视为一个特例,之后只处理奇数,这将使工作减半。

  3. 我的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