素数的筛法

一 写在开头

1.1 本文内容

本文实现了素数的筛法算法。

二 算法原理与实现

在写代码的过程中,时不时会遇到求解素数的任务,特意将素数求解方法总结成文章以备不时之需。素数的求解算法大概有两种。一种是枚举某一范围的数,然后逐个判断该数是否为素数。这种方法简单但效率不高。另一种方法是使用素数的筛法将某一范围内的所有素数筛选出来,然后再打表。筛法的原理很简单:从最小的素数2开始,依次将2的倍数给剔除,然后将后面没有被剔除的最小素数3的倍数依次剔除......重复上述操作就可以将范围内的所有合数给剔除掉,剩下的自然就是素数。该算法可以使用C语言实现,如下面的代码所示。

 1 #include <string.h>
 2
 3 /* 使用0和-1是为了使用内存填充函数memset */
 4 #define FALSE           (-1)
 5 #define TRUE            0
 6 #define MAX_RANGE_N     10000
 7
 8 unsigned int counter = 0;
 9 static char indexs[MAX_RANGE_N];
10 static int  primes[MAX_RANGE_N];
11
12 void ScreenPrimes(char *indexs, int *primes, unsigned int *counter)
13 {
14     int i, j, k;
15
16     /* 数组名做函数参数将退化成指针,因此需要乘于MAX_RANGE_N */
17     memset(indexs, TRUE, sizeof(indexs[0]) * MAX_RANGE_N);
18     indexs[0] = indexs[1] = FALSE;
19
20     /* 筛选过程 */
21     for (i = 2; i < MAX_RANGE_N; i++)
22         if (indexs[i] == TRUE)
23             for (j = i + i; j < MAX_RANGE_N; j += i)
24                 indexs[j] = FALSE;
25
26     /* 拷贝过程,其中k值表示范围内素数的个数 */
27     k = 0;
28     for (i = 0; i < MAX_RANGE_N; i++)
29         if (indexs[i] == TRUE)
30             primes[k++] = i;
31     *counter = k;
32 }

值得注意的是在memset函数中,sizeof(indexs[0])返回一个unsigned int值,如果MAX_RANGE_N很大的话,其和MAX_RANGE_N相乘会有溢出的危险。

有了上述的实现,要求打印前50个素数可以用下述代码实现。

 1 #include <stdio.h>
 2 #include <string.h>
 3
 4 /* 使用0和-1是为了使用内存填充函数memset */
 5 #define FALSE           (-1)
 6 #define TRUE            0
 7 #define MAX_RANGE_N     10000
 8
 9 unsigned int counter = 0;
10 static char indexs[MAX_RANGE_N];
11 static int  primes[MAX_RANGE_N];
12
13 void ScreenPrimes(char *indexs, int *primes, unsigned int *counter)
14 {
15     int i, j, k;
16
17     /* 数组名做函数参数将退化成指针,因此需要乘于MAX_RANGE_N */
18     memset(indexs, TRUE, sizeof(indexs[0]) * MAX_RANGE_N);
19     indexs[0] = indexs[1] = FALSE;
20
21     /* 筛选过程 */
22     for (i = 2; i < MAX_RANGE_N; i++)
23         if (indexs[i] == TRUE)
24             for (j = i + i; j < MAX_RANGE_N; j += i)
25                 indexs[j] = FALSE;
26
27     /* 拷贝过程,其中k值表示范围内素数的个数 */
28     k = 0;
29     for (i = 0; i < MAX_RANGE_N; i++)
30         if (indexs[i] == TRUE)
31             primes[k++] = i;
32     *counter = k;
33 }
34
35 int main()
36 {
37     int i;
38
39     ScreenPrimes(indexs, primes, &counter);
40     for (i = 0; i < 50; i++)
41         printf("%d ", primes[i]);
42     putchar(‘\n‘);
43
44     return 0;
45 }

原文地址:https://www.cnblogs.com/laizhenghong2012/p/8728537.html

时间: 2024-10-15 05:41:32

素数的筛法的相关文章

CodeForces 385C 素数朴素筛法,穷尽数的素数因子

//CodeForces 385C 素数朴素筛法,穷尽数的素数因子 1 #include "iostream" 2 #include "cstdio" 3 #include "cstring" 4 #include "algorithm" 5 using namespace std; 6 const int maxn = 10000100; 7 int tot, pr[maxn]; 8 bool is_pr[maxn]; 9

普通方法求素数与筛法求素数比较

20150806 package day06; /* * 普通方法求素数与筛法求素数比较 */ import java.util.*; public class TestSushu { public static void main(String[] args) { Scanner scan = new Scanner(System.in); System.out.print("查找范围2-"); int n = scan.nextInt(); long s1=System.curre

普通方法求素数与筛法求素数比較

20150806 package day06; /* * 普通方法求素数与筛法求素数比較 */ import java.util.*; public class TestSushu { public static void main(String[] args) { Scanner scan = new Scanner(System.in); System.out.print("查找范围2-"); int n = scan.nextInt(); long s1=System.curre

POJ-2689-Prime Distance(素数区间筛法)

链接: https://vjudge.net/problem/POJ-2689 题意: The branch of mathematics called number theory is about properties of numbers. One of the areas that has captured the interest of number theoreticians for thousands of years is the question of primality. A

POJ 2689 Prime Distance(素数区间筛法--经典题)

大致题意:给定[L,R]区间,找出区间内的每个素数 数据范围 : 1<=L< R<=2,147,483,647) R-L <=1,000,000. R的数值太大,所以不能直接筛[0,R]的,要空间和时间优化,用到区间筛法,另外注意不能用int,因为R和L都是满int的,中间有很多细节处理会爆int的,还要注意1不是素数,所以在区间筛中要特判一下,是个易错的地方 //1160K 16MS C++ 1539B #include<cstdio> #include<ios

【 数学基础】【素数线性筛法--欧拉筛法模板】【普通筛法的优化】

质数(素数):指大于1的所有自然数中,除了1和自身,不能被其它自然数整除的数 合数:比1大,但不是素数的数称为合数,合数除了被1和自身整除,还能被其它数整除 质因数(素因数或质因子):能整除给定正整数的质数,除1以外,两个没有其它共同质因子的正整数称为互质 1和0既非素数又非合数 素数筛法原理:素数的倍数一定不是素数. 实现步骤:用一个boook数组对maxn内的所有数进行标记,1为合数,0为素数,book初始化为0是假设全部数都为素数,从第一个素数2开始,把2的倍数标记为1,然后继续下一轮 欧

查找素数Eratosthenes筛法的mpi程序

思路: 只保留奇数 (1)由输入的整数n确定存储奇数(不包括1)的数组大小: n=(n%2==0)?(n/2-1):((n-1)/2);//n为存储奇数的数组大小,不包括基数1 (2)由数组大小n.进程号id和进程数p,确定每个进程负责的基数数组的第一个数.最后一个数和数组维度: low_value = 3 + 2*(id*(n)/p);//进程的第一个数 high_value = 3 + 2*((id+1)*(n)/p-1);//进程的最后一个数 size = (high_value - lo

素数相关?(有关素数的题持续更新中)x

素数(大体举几个栗子): 素数相关知识: 素数概念: 最大公约数只有1和它本身的数叫做质数(素数) 素数小性质: 1.大于一的整数必有素因数. 2.设p是素数,n是任意一个整数 能够推出p|n,(p,n)=1; 3.设p是素数,a,b为整数,若p|ab,则ab中至少有一个能被p整除 4.素数有无穷多个证明: (素数与整数之间的关系:1整除2互素) 假定正整数中只有有限个素数 设p1,p2……pk为从小到大排列起来的数 且N=p1*p2*……pk 设M=N+1 如果M为素数,那么M要大于p1,p2

睡前数学一小时之线性筛素数:

睡前数学一小时之线性筛素数:1,朴素的筛素数算法:埃拉托斯特尼筛法.这是个简单再简单不过的一个素数的筛法.只是名字很拉风.这就告诉我们,往往东西不好这没什么,名字很拉风.别人也不会记住.hhhhh.这个的思路就是.每一个数都是由一个质数与和数(质数也可以)的积组成.这也是质数与和数的定义.而这个它这个筛发,就是当遇到一个质数的时候开始枚举,枚举[1,n]中间关于这个质数的倍数.每次都枚举,每次都将算出的这个数打上标记.而最后整个区间内的质数枚举完后,整个区间内的质数也就筛选出来了.这个很简单.时