Eratosthenes筛选法求解质数
问题说明:
除了自身之外,无法被其它整数整除的数称之为质数,要求质数很简单,但如何快速的求出质数则一直是程式设计人员与数学家努力的课题, 在这边介绍一个着名的 Eratosthenes求质数方法。
解法:
首先知道这个问题可以使用回圈来求解,将一个指定的数除以所有小于它的数,若可以
整除就不是质数,然而如何减少回圈的检查次数?如何求出小于N的所有质数?
我们先来看一个丧心病狂的低效率的解决方式:
//检验质数
bool checkZS(int a)
{
for (int i = ;i < a;i++)
{
if ( == a%i)
{
return false;
}
}
return true;
}
首先我们写一个检验质数的函数,下面我们在主函数调用:
int n = ;
clock_t start,end;//用于计时
start = clock() ;
for(int i = ;i <= n;i++)
{
if (checkZS(i))
{
cout<<i<<" ";
}
}
end = clock();
cout<<"\n总共花费了"<<(long double)(end - start)/CLK_TCK<<"秒"<<endl;
好了,让我们看下在99999以内的质数算出来的运行结果:

时间花费了17秒,太慢了;下面我们想想怎样来改进算法!
首先知道这个问题可以使用回圈来求解,将一个指定的数除以所有小于它的数,若可以整除就不是质数,然而如何减少回圈的检查次数?如何求出小于N的所有质数?
首先假设要检查的数是N好了,则事实上只要检查至N的开根号就可以了,道理很简单,假设A*B = N,如果A大于N的开根号,则事实上在小于A之前的检查就可以先检查到这个数可以整除N。 不过在程式中使用开根号会精确度的问题, 所以可以使用 i*i <= N进行检查, 且执行更快 。
再来假设有一个筛子存放1~N,例如:
2 3 4 5 6 7 8 9 10 11 12 ........N
先将2的倍数筛去:
2 3 5 7 9 11 13........N
再将3的倍数筛去:
2 3 5 7 11 13 17 19........N
再来将5的倍数筛去,再来将7的质数筛去,再来将11的倍数筛去........,如此进行到最后留下的数就都是质数,这就是Eratosthenes筛选方法(Eratosthenes Sieve Method)
检查的次数还可以再减少,事实上,只要检查6n+1与6n+5就可以了,也就是直接跳过2与3的倍
数,使得程式中的if的检查动作可以减少。
下面我们上代码:
/*
问题:
除了自身之外,无法被其它整数整除的数称之为质数,要求质数很简单,但如何快速的
求出质数则一直是程式设计人员与数学家努力的课题, 在这边介绍一个着名的 Eratosthenes求质
数方法。
2013/7/18
张威
*/
#include <iostream>
#include <time.h>
using namespace std; #define n 99999 int main()
{
int a[n+];//建立一个数组,使a[i] == i,这样通过筛选,将非质数所在位置置0
for (int i = ;i <= n;i++)
{
a[i] = i;
}
clock_t start,end;//用于计时
start = clock() ; //每次进行筛选的数,进行优化,实际上只要筛选到 N开放就行
for (int i = ;i*i <= n;)
{
//从i处开始筛选(比i小的肯定不能被i整除)
for (int j = i;j <= n;j++)
{
//通过while循环.跳过中间置0区域
while( == a[j] && j <= n)
{
j++;
}
//假如a[j]能被i整除而且不相等(也就是说不是本身),就把这个位置数值置为0
if ( == a[j]%i && i != a[j])
{
a[j] = ;
}
}
//i的步进值优化,即跳过2或3的倍数,每次递增数加大
if((i-)% == )
i += ;
else if((i-)% == )
{
i += ;
}
else
{
i++;
}
}
end = clock();
for(int i = ;i <= n;i++)
{
if (a[i] != )
{
cout<<a[i]<<" ";
}
}
cout<<"\n总共花费了"<<(long double)(end - start)/CLK_TCK<<"秒"<<endl;
return ;
}
Eratostheness
上面标出了在减少算法中循环次数的优化方面所进行的修改,下面是运行结果:

两者之间的差距的话.......不说了,自己写的东西和这些算法相比就是渣渣!
下面上示例上面的代码:
#include <stdio.h>
#include <stdlib.h>
#define N 1000
int main(void) {
int i, j;
int prime[N+];
for(i = ; i <= N;i++)
prime[i] = ;
for(i = ; i*i <= N;i++) { // 这边可以改进
if(prime[i] == ) {
for(j = *i; j <= N;j++) {
if(j % i == )
prime[j] = ;
}
}
}
for(i = ; i < N;i++) {
if(prime[i] == ) {
printf("%4d ", i);
if(i % == )
printf("\n");
}
}
printf("\n");
return ;
}
示例代码
可以看到其实还是上面自己写的在示例的基础上还是做了些改善的!
Eratosthenes筛选法求解质数的更多相关文章
- Eratosthenes筛选法计算质数
<C和指针>第6章第4道编程题: 质数就是只能被1和本身整除的数.Eratosthenes筛选法是一种计算质数的有效方法.这个算法的第一步就是写下所有从2至某个上限之间的所有整数.在算法的 ...
- 每日一小练——Eratosthenes 筛选法
上得厅堂.下得厨房,写得代码.翻得围墙,欢迎来到睿不可挡的每日一小练! 题目:Eratosthenes筛选法 内容: 求质数是一个非常普遍的问题,通常不外乎用数去除.除到不尽时,给定的数就是质数.可是 ...
- Eratosthenes筛选法构造1-n 素数表
筛选法:对于不超过n的每个非负整数p,删除2p,3p,4p...当处理完所有数之后,还没没删除的就是素数. 代码中进行了相应的优化. 本代码功能,输入一个数,输出从1-该数之间的素数.功能待完善,可将 ...
- Eratosthenes筛选法
说到素数,最基本的算是一百以内的那些数了.这些数在数学竟赛中常常会被用到.比如说有这样一道题:“一百以内有多少在加2后仍然是素数的素数?”11和17就是这样的素数.如果对素数很熟悉的话,就能迅速得出答 ...
- [经典算法] Eratosthenes筛选求质数
题目说明: 除了自身之外,无法被其它整数整除的数称之为质数,要求质数很简单,但如何快速的求出质数则一直是程式设计人员与数学家努力的课题,在这边介绍一个著名的 Eratosthenes求质数方法. 题目 ...
- 使用埃拉托色尼筛选法(the Sieve of Eratosthenes)在一定范围内求素数及反素数(Emirp)
Programming 1.3 In this problem, you'll be asked to find all the prime numbers from 1 to 1000. Prime ...
- 筛选实现C++实现筛选法
每日一贴,今天的内容关键字为筛选实现 筛选法 分析: 筛选法又称筛法,是求不超越自然数N(N>1)的全部质数的一种方法.据说是古希腊的埃拉托斯特尼(Eratosthenes,约公元前274-19 ...
- 算法笔记_012:埃拉托色尼筛选法(Java)
1 问题描述 Compute the Greatest Common Divisor of Two Integers using Sieve of Eratosthenes. 翻译:使用埃拉托色尼筛选 ...
- C++实现筛选法
筛选法 介绍: 筛选法又称筛法,是求不超过自然数N(N>1)的所有质数的一种方法.据说是古希腊的埃拉托斯特尼(Eratosthenes,约公元前274-194年)发明的,又称埃拉托斯特尼筛子. ...
随机推荐
- ios copy/strong/weak..使用总结
总结 关于属性的这些选项的学习,做一下总结: 所有的属性,都尽可能使用nonatomic,以提高效率,除非真的有必要考虑线程安全. NSString:通常都使用copy,以得到新的内存分配,而不只是原 ...
- 常用 linux 命令(部分)
常用命令总结: 1. mkdir命令 mkdir dirname , 用来创建目录.该命令创建由dirname命名的目录.如果在目录名的前面没有加任何路径名,则在当前目录下创建由dirname指定的目 ...
- Project Management Process
Project Management ProcessDescription .............................................................. ...
- Maven集成Sonar
Sonar对maven提供了简单可配的支持,要做的事情很简单--在maven/conf下settings.xml <profiles></profiles>标签之间添加如下内容 ...
- Android:学习AIDL,这一篇文章就够了(上)
前言 在决定用这个标题之前甚是忐忑,主要是担心自己对AIDL的理解不够深入,到时候大家看了之后说——你这是什么玩意儿,就这么点东西就敢说够了?简直是坐井观天不知所谓——那样就很尴尬了.不过又转念一想, ...
- 再探Java基础——throw与throws
http://blog.csdn.net/luoweifu/article/details/10721543 异常处理机制 异常处理是对可能出现的异常进行处理,以防止程序遇到异常时被卡死,处于一直等待 ...
- nagios监控linux主机监控内存脚本
说明 工作包括两部分监控端(一二三)和被监控端(四) 一.nrpe.cfg中添加脚本 nrpe.cfg中添加命令索引 command[check_used_mem]=/usr/local/nagios ...
- UI进阶之--网易彩票手写plist文件,动态创建控制器与tableViewcell
点击右上角设置按钮 点击按钮后发生的事件:1. 控制器的跳转,进入新的控制器.view, 2. 跳转的时候对将要跳转的目标控制的子控件进行了布局.---通过手写plist文件的方式加载 为按钮注册单击 ...
- 详解 ASP.NET并行,异步,多线程
最近在学习.net4以上版本新特性的时候,发现在异步这方面提供了很多好玩的.以下Mark 2篇好文,温故而知新! http://www.cnblogs.com/wisdomqq/archive/201 ...
- Android Log图文详解
android.util.Log常用的方法有以下5个:Log.v() Log.d() Log.i() Log.w() 以及 Log.e() .根据首字母对应VERBOSE,DEBUG,INFO, WA ...