计算一定范围内素数个数的算法

本文对比了两种不同的素数计算算法:一种是基于素数性质的遍历算法,另一种是高效的素数筛选法。通过实验数据展示了不同算法的时间消耗,验证了素数筛选法在大规模数据集上的优越性。
部署运行你感兴趣的模型镜像

问题概述

问题:给定一个大整数N,计算开区间(1,N)的素数有多少?

  • 算法1:根据素数性质,a不能整除小于等于根号a的所有整数,则必为素数,从1到N遍历找出所有素数。
  • 算法2:素数筛选法,先剔除2的倍数,再剔除剩余的数中第一个数的倍数,直到剩余的数中第一个数大于根号N,此时剩下的数必全部为素数。

算法实现

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

#undef  TRUE
#define TRUE    1
#undef  FALSE
#define FALSE   0

typedef int BOOL32;

// a不能整除小于等于根号a的所有整数,则必为素数
void ChoosePrimeNumber_Slow(int dwTestSize)
{
	BOOL32* pbNumber = new BOOL32[dwTestSize];
	if (NULL == pbNumber)
	{
		printf("[ChoosePrimeNumber_Slow] New Error!\n");
		return;
	}
	memset(pbNumber, 0, dwTestSize*sizeof(int));

	int dwIndex, dwLoop = 0;
	*(pbNumber+2) = TRUE;
	for(dwIndex=3; dwIndex<dwTestSize; dwIndex++)
	{ 
		for(dwLoop=2; dwLoop<= dwIndex; dwLoop++)
		{
			if(dwIndex%dwLoop==0) 
				break;

			if (dwLoop > (int)sqrt((double)dwIndex))
			{
				*(pbNumber+dwIndex) = TRUE;
				break;
			}
		}
	}	
	// 计算素数个数
	int dwNum = 0;
	for(dwIndex=2; dwIndex<dwTestSize; dwIndex++) 
	{
		if(*(pbNumber+dwIndex))
			dwNum++;
	}
	printf("less than %d, there are %d prime number!\n", dwTestSize, dwNum);

	delete []pbNumber;
	return;
}

// 素数筛选法
void ChoosePrimeNumber_Fast(int dwTestSize)
{
	BOOL32* pbNumber = new BOOL32[dwTestSize];
//	BOOL32* pbNumber = (BOOL32*) malloc(sizeof(BOOL32)*dwTestSize);
	if (NULL == pbNumber)
	{
		printf("[ChoosePrimeNumber_Fast] New Error\n");
		return;
	}	
	memset(pbNumber, 0, dwTestSize*sizeof(int));

	int dwIndex, dwLoop = 0;
	*(pbNumber+2) = TRUE;
	for(dwIndex=3; dwIndex<dwTestSize; dwIndex++)
	{
		if(0 != dwIndex%2) 
			*(pbNumber+dwIndex)=TRUE;
		else
			*(pbNumber+dwIndex)=FALSE;
	}
		
	for(dwIndex=3; dwIndex<=(int)sqrt((double)dwTestSize); dwIndex++)
	{
		if(*(pbNumber + dwIndex))
		{
			for(dwLoop=dwIndex+dwIndex; dwLoop<dwTestSize; dwLoop+=dwIndex) 
				*(pbNumber+dwLoop)=FALSE;
		}
	}
	// 计算素数个数
	int dwNum = 0;
	for(dwIndex=2; dwIndex<dwTestSize; dwIndex++)
	{
		if( *(pbNumber+dwIndex))
			dwNum++;
	}	
	printf("less than %d, there are %d prime number!\n", dwTestSize, dwNum);

	delete []pbNumber;
//	free(pbNumber);
	return;
}

///////////////////////////
int main()
{
	clock_t cBegin, cTime = 0;

	int dwTestNum = 10000;
	for (int dwloop = 0; dwloop<5; dwloop++)
	{
		cBegin = clock();
		ChoosePrimeNumber_Slow(dwTestNum);
		cTime = clock() - cBegin;

#ifndef  WIN32
		cTime=cTime/1000;
#endif
		printf("[%d] Method ChoosePrimeNumber_Slow spend %d ms.\n\n", dwloop, cTime);
		
		cBegin = clock();
		ChoosePrimeNumber_Fast(dwTestNum);
		cTime = clock() - cBegin;
		
#ifndef  WIN32
		cTime=cTime/1000;
#endif
		printf("[%d] Method ChoosePrimeNumber_Fast spend %d ms.\n\n", dwloop, cTime);

		dwTestNum = dwTestNum*10;
	}

	return 0;
}

运行结果

  • CPU:Intel Core i3 2120
  • RAM:2G
less than 10000, there are 1229 prime number!
[0] Method ChoosePrimeNumber_Slow spend 2 ms.

less than 10000, there are 1229 prime number!
[0] Method ChoosePrimeNumber_Fast spend 0 ms.

less than 100000, there are 9592 prime number!
[1] Method ChoosePrimeNumber_Slow spend 41 ms.

less than 100000, there are 9592 prime number!
[1] Method ChoosePrimeNumber_Fast spend 1 ms.

less than 1000000, there are 78498 prime number!
[2] Method ChoosePrimeNumber_Slow spend 973 ms.

less than 1000000, there are 78498 prime number!
[2] Method ChoosePrimeNumber_Fast spend 32 ms.

less than 10000000, there are 664579 prime number!
[3] Method ChoosePrimeNumber_Slow spend 23846 ms.

less than 10000000, there are 664579 prime number!
[3] Method ChoosePrimeNumber_Fast spend 398 ms.

less than 100000000, there are 5761455 prime number!
[4] Method ChoosePrimeNumber_Slow spend 643918 ms.

less than 100000000, there are 5761455 prime number!
[4] Method ChoosePrimeNumber_Fast spend 4695 ms.

Press any key to continue

算法分析

从运行结果显而易见,算法2效率要远远高于算法1。

您可能感兴趣的与本文相关的镜像

Kotaemon

Kotaemon

AI应用

Kotaemon 是由Cinnamon 开发的开源项目,是一个RAG UI页面,主要面向DocQA的终端用户和构建自己RAG pipeline

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值