打印素数的各种算法
2012-01-11 22:12
337 查看
以前在网上看过一段这么描述素数的话说数论的研究对象归根到底是对素数的研究,因此如何高效地判断一个数是否是素数或者快速打印出一定范围内的素数的重要性不言而喻。下面我们来看一下几种关于素数判别的算法。
1、素数判定朴素算法
素数是这样一类特殊的数:它的因子只有1和它本身。由此我们可以得一种最为简单的判断一个数是否为素数的算法:对于某个数n,使2至n的开根作为除数,如果这些除数都不能整除n,则说明n是素数。这样的算法思路简单,但是时间复杂度却达到O(n*lg(n)),因此并不是高效的算法。
按照1中的方法来求素数,虽然可以达到目的,但是时间复杂度较高,是我们所不能容忍的,因此需要对上述方法进行改进。在通常所使用的算法中,一般时间复杂度较低的算法大多是利用筛选法,即将不符合条件的元素逐一排除,最后在集合中的元素都是满足条件的。求解素数同样可以利用这种方法,例如需要打印20以内的素数,则有
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
第一步:取出第一个数2,去除集合中其他能被2整除的数。
2 3 5 7 9 11 13 15 17 19 21 23 25 27 29
第二步:取出第二个数3,去除集合中其他能被3整除的数。
2 3 5 7 11 13 17 19 23 25 29
第三步:取第三个数5,去除集合中其他能被5带队的数。
2 3 5 7 11 13 17 19 23 29
第四步:取第四个数7,因为7的平方大于30,因此中止操作,此时集合中剩余的数都是素数。
这种方法的时间复杂度较方法1有所提高,达到O(nlg(n))。
3、利用文件节约运行时间
方法2虽然对方法1有所改进,但是在工程应用中的可操作性并不强,主要是因为它们在运行时需要耗费很多时间来判断一个数是否为素数。因为我们可以从这个方面来着手改进,使得在工程应用上更加高效。
在实际应用中,我们一般是将素数事先计算好,保存在文件中(因为指定范围的素数是固定的,因此可以这样处理),在程序启动时,加载这个文件,不管是打印还是查找操作都可以在O(lg(n))(二分查找)甚至O(1)(Hash查找)时间内完成。
其实很多应用都是将数据事先计算出来保存到文件中,在程序运行时直接读取文件,从而避免计算所耗费的大量时间。例如我们启动软件时读取的配置文件,以及游戏程序里的特效数据文件。
4、编译时完成数据计算节约运行时间
随着计算机硬件技术的发展,内存已经不再是奢侈品,而且从内存中读取数据的速度要远远快于从硬盘读取数据。因此在实际应用中可以将运行时花费较多时间计算的数据,在编译时完成计算保存在内存中,那么在运行时可以直接在内存中读取这部分数据,从而大大节约软件运行时间。
在C++中,利用编译器对模板的特化处理可以实现在编译期计算指定范围内的素数,并在运行时直接将计算出的结果打印出来。
在J***A Web开发中,涉及到大量数据处理的程序可以做成启动型servlet,将Web程序部署到Tomcat服务器中,在Tomcat启动时,servlet中的程序优先执行,将计算得到的数据保存至服务器内存中,方便用户使用。
5、正则表达式判定素数
在网上看到其他人提到可以利用正则表达式可以实现判定指定的数是否为素数。具体的正则表达式为
原理:加号表示匹配一次或多次(加上一个问号表示非贪婪模式),\1表示引用括号里的内容,头尾的^和$则避免了部分匹配的情况。这样,^(11+?)相当于枚举除数大小,而\1+$则用于检验整个字符串是否能按此大小恰好分完。如果除得尽,则匹配成功,字符串长度为合数。另外,前面的^1?$只是为了处理n=0或n=1时的特殊情况,而符号|则表示“或者”的意思。
1、素数判定朴素算法
素数是这样一类特殊的数:它的因子只有1和它本身。由此我们可以得一种最为简单的判断一个数是否为素数的算法:对于某个数n,使2至n的开根作为除数,如果这些除数都不能整除n,则说明n是素数。这样的算法思路简单,但是时间复杂度却达到O(n*lg(n)),因此并不是高效的算法。
#include <stdio.h> #include <math.h> bool isPrime(int n) { if(n < 2) return false; for(int i = 2; i <= sqrt(n); ++i) { if(!(n % i)) { return false; } } return true; } int main() { for(int i = 0; i <= 50; ++i) { if(isPrime(i)) { printf("%d\n", i); } } return 0; }2、利用筛选法求出指定范围内的素数
按照1中的方法来求素数,虽然可以达到目的,但是时间复杂度较高,是我们所不能容忍的,因此需要对上述方法进行改进。在通常所使用的算法中,一般时间复杂度较低的算法大多是利用筛选法,即将不符合条件的元素逐一排除,最后在集合中的元素都是满足条件的。求解素数同样可以利用这种方法,例如需要打印20以内的素数,则有
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
第一步:取出第一个数2,去除集合中其他能被2整除的数。
2 3 5 7 9 11 13 15 17 19 21 23 25 27 29
第二步:取出第二个数3,去除集合中其他能被3整除的数。
2 3 5 7 11 13 17 19 23 25 29
第三步:取第三个数5,去除集合中其他能被5带队的数。
2 3 5 7 11 13 17 19 23 29
第四步:取第四个数7,因为7的平方大于30,因此中止操作,此时集合中剩余的数都是素数。
这种方法的时间复杂度较方法1有所提高,达到O(nlg(n))。
3、利用文件节约运行时间
方法2虽然对方法1有所改进,但是在工程应用中的可操作性并不强,主要是因为它们在运行时需要耗费很多时间来判断一个数是否为素数。因为我们可以从这个方面来着手改进,使得在工程应用上更加高效。
在实际应用中,我们一般是将素数事先计算好,保存在文件中(因为指定范围的素数是固定的,因此可以这样处理),在程序启动时,加载这个文件,不管是打印还是查找操作都可以在O(lg(n))(二分查找)甚至O(1)(Hash查找)时间内完成。
其实很多应用都是将数据事先计算出来保存到文件中,在程序运行时直接读取文件,从而避免计算所耗费的大量时间。例如我们启动软件时读取的配置文件,以及游戏程序里的特效数据文件。
4、编译时完成数据计算节约运行时间
随着计算机硬件技术的发展,内存已经不再是奢侈品,而且从内存中读取数据的速度要远远快于从硬盘读取数据。因此在实际应用中可以将运行时花费较多时间计算的数据,在编译时完成计算保存在内存中,那么在运行时可以直接在内存中读取这部分数据,从而大大节约软件运行时间。
在C++中,利用编译器对模板的特化处理可以实现在编译期计算指定范围内的素数,并在运行时直接将计算出的结果打印出来。
在J***A Web开发中,涉及到大量数据处理的程序可以做成启动型servlet,将Web程序部署到Tomcat服务器中,在Tomcat启动时,servlet中的程序优先执行,将计算得到的数据保存至服务器内存中,方便用户使用。
5、正则表达式判定素数
在网上看到其他人提到可以利用正则表达式可以实现判定指定的数是否为素数。具体的正则表达式为
^1?$|^(11+?)\1+$使用这种方法需要将给定的数转化为全“1”的字符串,例如2要写成“11”,3要写成“111”,10要写成”1111111111“。测试程序如下:
<script type="text/javascript"> var st="1"; document.write("1~100之间的所有素数如下:", "<br/>"); for(var i = 2; i < 100; i++) { if(!/^1?$|^(11+?)\1+$/.test(st = st + "1")) { document.write(i, "<br/>"); } } document.close(); </script>
原理:加号表示匹配一次或多次(加上一个问号表示非贪婪模式),\1表示引用括号里的内容,头尾的^和$则避免了部分匹配的情况。这样,^(11+?)相当于枚举除数大小,而\1+$则用于检验整个字符串是否能按此大小恰好分完。如果除得尽,则匹配成功,字符串长度为合数。另外,前面的^1?$只是为了处理n=0或n=1时的特殊情况,而符号|则表示“或者”的意思。
相关文章推荐
- hdu1695 综合数论 欧拉函数 分解质因子 容斥原理 打印素数表 各种模板
- 设计一种算法,打印八皇后在8*8棋盘上的各种摆法
- 打印1000内的所有素数,算法复杂度O(n)
- 整数算法训练04—求100以内的素数,全部打印出来
- 算法系列--打印素数(详解)
- 算法--打印素数--死记硬背也要牢记
- 各种高性能算法 求素数 太牛 挑战算法
- 打印质数的各种算法
- 打印小票时自动换行算法,可处理各种字符混排
- 打印小票时自动换行算法,可处理各种字符混排
- 用数组实现打印小于10000的素数的快速算法
- Java中循环问题:for,while,do-while 各种练习(打印上三角、下三角、输出100以内的素数、水仙花、最大公约、最小公倍数、分解质因数、兔子问题)
- iOS 算法面试题(打印2-100之间的素数、求两个整数的最大公约数、查找字符串的位置)~demo
- 打印质数的各种算法
- 打印质数的各种算法
- 打印100~200之间素数的优化算法
- 算法15:打印中两个整数范围内的所有素数,例如:(12, 15) ->13
- 简单的算法题,包括1.打印100——200之间的的素数2.输出乘法口诀表3.判断1000年——2000年之间的闰年,给出完整代码
- 打印质数的各种算法----来自酷壳(www.coolshell.com)
- 打印100到400之间的素数的4种算法