求素数的个数

求素数的个数(三种方法)

1、实验目的与基本要求:
熟悉素数的判定及算法的优化。

2、实验内容:
求2~n素数的个数。
操作菜单要求:
输入n,输出2~n素数的个数。
该实验内容以“long”作为数据元素n的数据类型即可。

#include <stdio.h>
#include <math.h>
#include <time.h>
#include <string.h>


bool prime(long n);
void primeTime(long a);

void AiShi(long b); 

void Oula(long c);

int main()
{
	long long int n;
	printf("素数:输入n的值:");
	scanf("%ld",&n);
	AiShi(n);
	Oula(n);
	prime(n);
	primeTime(n);
	
	return 0;
}

埃氏筛选法实现思路:首先,需要一个存储素数的数组和一个筛选是否为素数的数组,数组存储21052375个数,其中元素的值为0(代表素数)。由于最小的数字2是素数。将表中2的倍数都划去,当然也包括其本身,(即筛选数组的元素值为1,代表合数)。以此类推,每次表中剩下的最小数字m都是素数,然后将表中所有的m的倍数划去。如此反复操作,便能筛出n以内的所有素数。

const int x = 21000000;
bool shaixuan[x];	//筛选 是否为素数的数组  1为合数 0为素数 
int sushu[x];		//创建存取素数的数组 

void AiShi(long b)
{
	clock_t t3;
	t3 = clock();
	int count = 0; 
	for(long i = 2; i <= b; i++)
	{
		if(shaixuan[i] == 0)				// 默认为 0 -> 素数 
		{
			sushu[++count] = i;			
			for(long j = 2; j <= b / i; j++)
			{
				if(i * j >= b)
				{
					break;
				}
				else
				{
					shaixuan[i * j] = 1;		// 1 代表都是素数的倍数(合数)->不是素数 
				}
			}
		}	
	}
	
	clock_t t4;
	t4 = clock() - t3;
	
	printf("方法2:\n");
	printf(" 结果:2到%ld的素数个数为:%ld\n",b,count-1);
	printf(" 用时:%lf秒\n",(float)t3/CLOCKS_PER_SEC);	
		
} 

欧拉筛选法实现思路:此算法是在埃氏算法的基础上多了判断的步骤,从而消去了这种重复标记的情况,思路是用合数中的一个因数筛掉这个合数。具体的实现方式是利用已经求得的素数,第一重循环将区间内的数从小到大遍历,第二重循环将已求得的素数从小到大遍历,将这个数和素数的乘积标记为合数。如果一个数能被素数整除,跳出循环。如此反复操作,便能筛出n以内的所有素数。

#define yxx 21000000

bool shaixuan2[yxx];			//筛选 是否为素数的数组 
int sushu2[yxx];				//创建存取素数的数组
int num = 0;				//素数个数 


void Oula(long c)
{
	int count = 0;
	
	clock_t t5;
	t5 = clock();
	
	//0标记不是素数,1标记是素数 
    memset(shaixuan2,1,sizeof(shaixuan2));		//shaixuan素数所有元素标记 1 
    shaixuan2[0] = shaixuan2[1] = 0;				//下标为0和1的元素(0/1)不是素数,标记 0				
    for(int i = 2;i <= yxx;i++)
    {
        if(shaixuan2[i])
        {
        	sushu2[++count] = i;
		}
        for(int j = 1; j <= count && i * sushu2[j] <= yxx;j++)	//合数在给定范围内
        {
            shaixuan2[i * sushu2[j]] = 0;
            if(i % sushu2[j] == 0)
            {
            	break;
			}       
        }
    }
    
    clock_t t6;
	t6 = clock() - t5;
    
    printf("方法3:\n");
    printf(" 结果:2到%ld的素数个数为:%ld\n",c,count);
	printf(" 用时:%lf秒\n",(float)t5/CLOCKS_PER_SEC);
}

暴力法:也就是循环2~n个数字判断是素数就返回,不是素数就继续下一个数接着判断。

bool prime(long n)
{
	for(long i = 2; i <= (long)sqrt(n); i++)
	{
		if(n % i == 0)
		{
			return 0;
		}
	}
	return 1;
}

void primeTime(long a)
{
	clock_t t1;
    long count = 0;
	t1 = clock();
	for(long j = 2; j <= a; j++)
	{
		if(prime(j))
		{
			count++;
		}
	}
	
	clock_t t2;
	t2 = clock() - t1;
	
	printf("方法1:\n");
	printf(" 结果:2到%ld的素数个数为:%ld\n",a,count);
	printf(" 用时:%lf秒\n",(float)t1/CLOCKS_PER_SEC);
	
}

运行结果(方法1:暴力法,方法2:埃氏筛选法,方法3:欧拉筛选法)
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值