线性素数筛选(linear sieve for prime number)

偶然发现了这个和stackoverflow很像的地方。打算写些专栏,一方面,记录本身学到的东西。另外一方面,也把这些分享给你们。不管是内容错误仍是解释方式很差,都欢迎各位拍砖。转载到其余平台前也请通知我。

本篇的IDE是Pycharm,使用的是Python 3 的基本interpreter

问题起源

这个问题起源于我在想寻找最大素数的时候诞生的。出现这个问题,一开始的想法是经过暴力破解来达成目的,举例的话,就以寻找第20000个素数开始吧算法

算法演绎

import time

def func(num):
    # since once i larger than num//2, num will not be divisible by any i increment
    for i in range(2, num//2+1):
        if num % i == 0:
            return 0
    return 1

def find_prime():
    num = 1
    count = 0
    # find the 20000th prime in the world!
    primeCount = 20000
    while count < primeCount :
        num += 1
        count = func(num)+count
    return num

# count time
start = time.time()
num = find_prime()
end = time.time() -start
print("find %s in %s seconds" % (num,end))

结果是:优化

find 224737 in 151.33826684951782 seconds

Process finished with exit code 0

151秒,感受花了好长时间,显然这不是一个有效率的方法。spa

算法分析

因为咱们每次寻找的素数时,都从2开始,逐渐上除,最后到num/2为止,确认是不是素数。那所用的效率就是
$$ O(N^2) $$code

查找了一些文献之后,看到了一种方法:线性素数筛选:埃拉托斯特尼筛法(Sieve of Eratosthenes图片

在每次咱们肯定素数的时候,将其以后的有关合数进行排除,每一次在寻找下个素数时,必然能一次性找到,而不用逐渐去加1来寻找。接着继续排除其有关合数。那这样所用效率就变成了
$$O(N*log(log(N)))$$
这里第一个N来自于寻找下个素数,而log(log(N)来自于寻找各个素数的合数,而这个算法,也须要一个$$O(N)$$的存储空间,我这里用了5000000的存储空间。而这是一个伪的polynomial算法。
wiki中显示了一种优化方法,能够在$$O(N)$$中完成,但相对的须要$$O(n^{1/2}\log\log n/\log n)$$的存储空间。这里给予连接,Paul Pritchardip

算法演绎

def fast_find_prime(n,limit =5000000):
    if limit %2 != 0 :
        limit+=1
    # Assume all numbers are prime number
    primes = [True] *limit
    # Eliminate 0 and 1
    primes[0], primes[1] = [None] *2
    # set count
    count = 0
    # enumerate numbers
    for ind, val in enumerate(primes):
        if val is True:
            # set number false when it is not prime
            # ind will skip not prime numbers
            primes[ind*2::ind] = [False] * (((limit-1)//ind)-1)
            count += 1
        if count == n: return  ind
    return False

#count time
start = time.time()
num = fast_find_prime(20000)
end = time.time() -start
print("find %s in %s seconds" % (num,end))

结果为:rem

find 224737 in 0.427901029586792 seconds

Process finished with exit code 0

0.4秒,很是迅速。get

相关算法

在论坛中提到过一种 Sieve of Atkin 的算法。在速度上有略微提高,可是它的算法是主动忽略二、三、5的相关合数,实际意义并非很大。有兴趣的同窗也能够看一下。博客

无关问题

===============================这里是与主题无关的分割线===============================

初用segment fault感受仍是不太同样,在之前的写博客习惯下,随便试了一些方法,除了tab以外尚未找到特别有趣的特殊格式。特别例如平方号等特殊符号,没可以实验出来。官方是否能出一份文章特殊符号和格式的使用说明呢?it

以上问题,很是感谢高阳sunny的迅速回复,祝segment fault越办越出众!

一栏一槽

===============================这里是与上述都无关的分割线===============================

据说一位同窗要去人民大学读研,去寒暄了一下:
“你要去人大?”
“恩”
“何时去当常委?dog rich, don't forget!”
“......”
因而我回到美帝之后,发现又遭到报应性冷空气了。。。

图片描述

14年时初,拜访康村,和cornell的同窗冒着雪天,黄昏时分在康村取景拍下的照片
相关文章
相关标签/搜索