`
ajuanlong
  • 浏览: 105098 次
社区版块
存档分类
最新评论

改进的筛素数法

 
阅读更多

最简单的筛素数法方法就是从2开始,将所以2的倍数去掉,然后从3开始,将3的倍数去掉。根据这样很容易写出代码,下面代码就是是筛素数法得到100以内的素数并保存到primes[]数组中。

可以看出这种会有很多重复访问,如在访问flag[2]和flag[5]时会各访问flag[10]一次。因此最好想方法来减少这种重复访问,让flag[]数组的每个元素只被访问一次。可以这样考虑——简单的筛素数法是利用一个素数的倍数必须不是素数,同样任何一个数与其它所有素数的乘积必然也不是素数(这是因为每个合数必有一个最小素因子)。

为了试验这种想法,先用2到10之间的数来验证下。

2,3,4,5,6,7,8,9,10 初始时所以flag都是无标记的。

第一步 访问2,flag[2]无标记所以将2加入素数表中,然后将2与素数表中的所有数相乘得到的数必定不是素数,2*2=4因此标记flag[4]。

2,3,4,5,6,7,8,9,10

第二步 访问3,flag[3]无标记所以将3加入素数表中,将3与素数表中的所有数相乘得到的数必定不是素数,3*2=6,3*3=9因此标记flag[6]和flag[9]。

2,3,4,5,6,7,8,9,10

第三步 访问4,flag[4]有标记所以4不加入素数表中,将4与素数表中的所有数相乘得到的数必定不是素数, 4*2=8,4*3=12因此标记flag[8]。

2,3,4,5,6,7,89,10

第四步 访问5,flag[5]无标记所以将5加入素数表中,将5与素数表中的所有数相乘得到的数必定不是素数,5*2=10,5*3=15因此标记flag[10]。

2,3,4,5,6,7,8910

第五步 访问6,flag[6]有标记所以6不加入素数表中,将6与素数表中的所有数相乘得到的数必定不是素数, 6*2=12,6*3=18,6*5=30。

2,3,4,5,6,7,8910

后面几步类似,代码不难写出:

这份代码对不对了?仔细回顾下分析过程,可以发现有些数据还是被访问多次了,这当然不是我们希望的结果,我们的要求是让每个合数仅被它的最小素因子筛去一次。比如12,它的最小素因子是2,所以就只应该被在计算6*2时去访问,而且不应该在计算4*3时去访问,同理18也只应该被在计算9*2时去访问,而且不应该在计算6*3时去访问。

找到原因后,再来思考如何解决。6*3不行而9*2可以了,是因为6是2的倍数,所以在计算6*2之后就不能再将6与比2大的素数相乘,这些相乘的结果必定会导致重复计算。因此对于任何数来说,如果它如果是该素数的倍数那么它就不能再与素数表中该素数之后的素数相乘了,如9是3的倍数,所以在9*3之后就不能再去用计算9*5了。因此在代码中再增加一行判断语句:

想知道这二种筛素数法方法的区别吗?现在对求2到1亿之间的素数进行测试,看看区别到底会有多大,测试代码如下:

测试结果如图所示:

可以看出,效率有4倍之差。改进还是比较可观。有兴趣的同学可以参考下一篇《位操作基础篇之位操作全面总结》所讲到的空间压缩技巧来将改进后的筛素数法方进行空间压缩。

文章最后作下小小总结:

1.普通的筛素数的原理是一个素数的倍数必须不是素数。

2.改进的筛素数的原理是每个合数必有一个最小素因子,根据每个最小素因子去访问合数就能防止合数被重复访问。

另外,筛素数法还有很多种改进手段,在数学论坛上可以去研读一下,本文就不再深究了。

转载请标明出处,原文地址:http://blog.csdn.net/morewindows/article/details/7347459

如果觉得本文对您有帮助,请点击‘顶’支持一下,您的支持是我写作最大的动力,谢谢。

分享到:
评论

相关推荐

    用C语言思想改写的用筛法求质数程序.rar_筛法 质数

    判断质数的改进方法。

    最快素数算法(绝非线性筛选)1.6秒算出1亿内所有素数

    我对其进行了革命性的数据结构改进,空间复杂度从2个O(n)降低到1/6个O(n),程序的算法描述更加简洁,改用C++实现,我认为算法效率已经达到了素数算法的极限。 注:创建的内存大小不要超过内存,否则效率下降

    素数分布的台阶理论

    素数分布的台阶理论,罗贵文,许作铭,本文通过将正整数分成由不同的有限数字组成的无限个台阶,采用改进的埃塔筛法,即为台阶筛法,根据不同台阶中的素数个数与平均值�

    素数定理的一个初等证明

    素数定理的一个初等证明,罗贵文,许作铭,本文利用改进的埃塔筛法,研究多次取整算法与素数及平均值的关系,给出了素数定理的一个初等证明

    Eratostheness筛法的推广与素数分布 (2003年)

    将计算机素数的筛法进行改进并将其推广为分段筛法,扩大计算范围,提高了运行速度,计算出100亿以下素数表和2000亿以下的素数分布。

    C#,质数(Prime Number)的四种算法源代码和性能比较

    质数又称素数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数;...(1)质数筛(改进的埃拉托斯特尼筛法); (2)暴力法; (3)米勒-罗宾随机算法; (4)改进的米勒-罗宾随机算法;

    歌德巴赫猜想的初等证明

    歌德巴赫猜想的初等证明,罗贵文,许作铭,本文利用改进的埃塔筛法,研究了很多取整算法与歌德巴赫素数表示法个数及其平均值之间的关系,找到了一种计算歌德巴赫素数表示法

    数论的方法 [闵嗣鹤 著] 2011年版

    第一篇介绍数论中几种重要的初等方法,包括шhиpeльmah的密率论及由此发展而成的渐近密率与本性分量的理论,brun的筛法与更精密的selberg筛法,素数定理的初等证明与弱型goldbach问题的初等解法等;第二篇介绍...

    全面的算法代码库

    Eratosthenes素数筛法 Sieve-of-Erotosthenes 指针版的单向链表 Singly-Linked-List(Pointer) 跳表 Skip-List ST表 Sparse-Table 伸展树 Splay 博弈论SG函数 Sprague-Grundy 栈的基本操作 Stack 递推法求解无...

    常用算法代码

    | 筛素数 [1..N] 26 | 高效求小范围素数 [1..N] 26 | 随机素数测试(伪素数原理) 26 | 组合数学相关 26 | POLYA 计数 27 | 组合数 C(N, R) 27 | 最大 1 矩阵 27 | 约瑟夫环问题(数学方法) 27 | 约瑟夫环...

    Linux高级bash编程

    高级bash编程 高级Bash脚本编程指南(一) ... 一个"改进过"的 strings 命令 12-32. 在一个脚本中使用 cmp 来比较2个文件. 12-33. basename 和 dirname 12-34. 检查文件完整性 12-35. Uudecod 编码后的...

    Advanced Bash-Scripting Guide <>

    找anagram(回文构词法, 可以将一个有意义的单词, 变换为1 个或多个有意义的单词, 但 是还是原来的子母集合) 16-1. 使用exec 重定向标准输入 16-2. 使用exec 来重定向stdout 16-3. 使用exec 在同一脚本中重定向stdin...

Global site tag (gtag.js) - Google Analytics