求质数总结

质数又称素数。指在一个大于1的自然数中,除了1和此整数自身外,没法被其他自然数整除的数。

一、判断一个数是否为质数

首先根据定义,最简单的判断一个数n是否为质数的方法,就是从2开始对小于n的所有数,依次判断是否能整除n,若都不能整除就是质数。

bool IsPrime(int n)
{
	if(n == 1)
		return false;
	for(int i = 2; i < n; i++)
		if(n % i ==0)
			return false;
	return true;
}

我们再稍微改进一下,我们可以先判断一下2能不能整除n,然后2以上的偶数就不需要再判断了,因为2不能整除n那么含有因子2的数肯定也不能整除n。再者,我们根本不需要循环到n,若两个数的乘积为n,那么肯定有一个因子是小于sqrt(n)的,所以,循环的上限可以取sqrt(n)。于是就有:

bool IsPrime(int n)
{
	if(n == 2)
		return true;
	if(n == 1 || (n & 1))
		return false;
	int k = (int)sqrt(n);
	for(int i = 3; i <= k; i += 2)
		if(n % i == 0)
			return false;
	return true;
}

上面是过滤掉了2的倍数,计算量变为原来的二分之一,我们也可以把3的倍数过滤掉,也就是只判断3是否能整除n,其它3的倍数就不需要判断了,计算量就可以变为原来的三分之一。也就是只剩6*k+1和6*k+5(k为整数)这些数,因为其他数都含有因子2或3,n若不能被2或3整除,那么n也不能被6*k,6*k+2,6*k+3,6*k+4这些数整除,就不需要判断这些数能否整除n了,这样又减少了判断量。

bool IsPrime(int n)
{
	if((n == 2) || (n == 3))
		return true;
	if((n == 1) || ((n & 1) == 0) || ((n % 3) ==0))
		return false;
	int k = (int)sqrt(n);
	int step = 4;
	for(int i = 5; i <= k; i += step)
	{
		if(n % i == 0)
			return false;
		step = 6 - step;
	}
	return true;
}

二、找出区间内的所有质数

要求区间内的所有质数,首先可以用以上判断单个质数的方法挨个寻找,但是太慢了。。。

这类问题主要的就是筛选法了。筛法求质数的主要思想就是,从小到大,当判断完一个数K是否为质数后,把后面的所有的K的倍数(含因子K)都去掉。

#define N 1000000
bool isPrime[N];
int i;
memset(isPrime, true, sizeof(isPrime));
isPrime[1] = false;
//筛掉大于2的偶数
for(i = 4; i < N; i += 2)     
    isPrime[i] = false;  
int bound = sqrt(N);  
//用sqrt(N)以内的质数去筛掉后面含有质数因子的元素  
for(i = 3; i <= bound; i += 2)               
{
	//从3开始的奇数,如果是质数就去筛掉以自己为因子的元素,不是质数跳过
	if(false == isPrime[i]) 
		continue;  
	int step = i << 1;   
	//i为质数,则从i*i开始筛,以2*i为步长(因为偶数已被筛掉,小于i*i的非质数,已被小于i的质数筛掉)
	for(int j = i * i ; j < N ; j += step) //含有质数因子i,筛掉      
		isPrime[j] = false;            
}

若求两个大数之间的质数,也可以用筛法

如求N1和N2之间的质数1000000000 <= N1 < N2 < 2^32 and 1 < N2 – N1 < 1000000

bool isPrime[1000000];
int prime[70000]; //保存小于65536的质数(可以筛unsigned int范围内的数),筛法求出
int primeCnt;     //小于65536的质数个数
int i, j;
/*
求小于65536的质数,保存在prime数组中
*/
int N1 = 100000000;
int N2 = 101000000;
int D = N2 - N1;
memset(isPrime, true, sizeof(isPrime));
for(i = 0; i < primeCnt; i++)
{ 
    int k = N2 % prime[i]; 
    //可知 N2-k 含质因子prime[i],不是质数,N2 - k - x*prime[i](x为整数)都不是质数数,筛掉  
	int step = prime[i]; 
	int j = D - k; 
	// N2 - k 对应于数组下标 D - k, N2 - k - x * prime[i] 对应于数组下标 j - x * prime[i]; 
	while(j >= 0) 
	{
		isPrime[j] = false; //isPrime[j] 代表 N1 + j 是否是质数
		j -= step; 
	}
}

    原文作者:WalkingInTheWind
    原文地址: https://blog.csdn.net/WalkingInTheWind/article/details/7040004
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞