打表法判断素数

       说明:本处的素数判断函数,只适用于int型。在无符号int和int64上的正确性还没有进行严格的验证。

       从方便性来说,用普通的素数模板即可解决一般问题。打表法只有在需要判断大量很大的整数是否为素数时,才能体现出效率优势。

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

方法一:普通法基本模板

#include <cmath>

bool isprime(int x)  
{
    int logo = 0, i, m;  
    if (x==2 || x==3) logo = 1;  
    else if ((x>4) && (x%2))  
    {
        m = sqrt(x);
        for (i = 3; (i<=m) && (x%i); i += 2);  
        if (i > m) logo = 1;  
    }  
    return logo;
}

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

方法一效率测试

#include <cmath>
#include <ctime>
#include <iostream>
#include <cstdlib>
#include <climits>
using namespace std;

clock_t start__;
#define tic start__=clock()
#define toc cout<<(clock()-start__)*1000/CLOCKS_PER_SEC<<"ms\n"

bool isprime(int x)  
{
    int logo = 0, i, m;  
    if (x==2 || x==3) logo = 1;  
    else if ((x>4) && (x%2))  
    {
        m = sqrt(x);
        for (i = 3; (i<=m) && (x%i); i += 2);  
        if (i > m) logo = 1;  
    }  
    return logo;
}

int main()
{
	int i, t, sum;
	
	tic; 	
	printf("效率测试:判断1百万个%d至%d的“随机数”是否为素数\n",
		0, RAND_MAX);
	
	srand(time(NULL));
	for (sum = i = 0; i < 1000000; i++)
	{
		t = rand();
		sum += isprime(t);
	}
	printf("共统计出%d个素数\n用时:", sum);
	toc; printf("\n");
	
	tic; 	
	printf("效率测试:判断1百万个%d至%d的“随机数”是否为素数\n",
		_I32_MAX-RAND_MAX, _I32_MAX);
	
	srand(time(NULL));
	for (sum = i = 0; i < 1000000; i++)
	{
		t = _I32_MAX - rand();
		sum += isprime(t);
	}
	printf("共统计出%d个素数\n用时:", sum);
	toc; printf("\n");
	
	return 0;
}

打表法判断素数_第1张图片
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

方法二:打表法

       原理:在pri[0]存储事先要打好多少个素数。init_prime在pri[1]存储2,然后p从3开始,对每个奇数遍历,如果p能整除比p小的所有素数,那么p就是素数,在pri[]末尾添加p。直到在pri[]填充完pri[0]个素数为止。

       在isprime函数,如果输入的数,小于pri素数表最大的数,则在pri中二分查找x是否存在,存在则为素数,否则不是素数。如果x大于素数表最大的数,则遍历比sqrt(x)小的所有素数,当且仅当都不能被整除时,x为素数。

       从isprime函数的原理看出,素数表的大小要合理。因为素数判断范围由pri[pri[0]]^2决定。要计算int,最小设置pri[0]=5000。

       实际运用中,可以把pri设为全局变量。

#include <cmath>
#include <algorithm>

void init_prime(int pri[])
{
	int i, n, p;
	pri[1] = 2;
	for (p=1, n=2; n <= pri[0]; n++)
	{
		do
		{
			i = 1; p += 2;
			while (i<n && p%pri[i]) i++;
		}while (i != n);
		pri[n] = p;
	}
}

bool isprime(int x, int pri[])
{
	if (x <= pri[pri[0]]) return x == *lower_bound(pri+1, pri+pri[0]+1, x);
	else
	{
		int m = sqrt(x), i = 0;
		while (pri[++i] < m) if (x%pri[i]) return 0;
		return 2;
	}
}
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
方法二效率测试

#include <cmath>
#include <ctime>
#include <iostream>
#include <cstdlib>
#include <climits>
#include <algorithm>
using namespace std;

clock_t start__;
#define tic start__=clock()
#define toc cout<<(clock()-start__)*1000/CLOCKS_PER_SEC<<"ms\n"

void init_prime(int pri[])
{
	int i, n, p;
	pri[1] = 2;
	for (p=1, n=2; n <= pri[0]; n++)
	{
		do
		{
			i = 1; p += 2;
			while (i<n && p%pri[i]) i++;
		}while (i != n);
		pri[n] = p;
	}
}

bool isprime(int x, int pri[])
{
	if (x <= pri[pri[0]]) return x == *lower_bound(pri+1, pri+pri[0]+1, x);
	else
	{
		int m = sqrt(x), i = 0;
		while (pri[++i] < m) if (!(x%pri[i])) return 0;
		return 2;
	}
}

int main()
{
	int pri[10001] = {0};
	
	tic;
	pri[0] = 5000; init_prime(pri);
	printf("初始化%d大小的素数表用时", pri[0]); toc;
	cout << "素数判断范围:" << pri[pri[0]]*1.0*pri[pri[0]] << endl << endl;
	
	tic;
	pri[0] = 10000; init_prime(pri);
	printf("初始化%d大小的素数表用时", pri[0]); toc;
	cout << "素数判断范围:" << pri[pri[0]]*1.0*pri[pri[0]] << endl << endl;
	
	
	
	int i, t, sum;
	
	tic; 	
	printf("效率测试:判断1百万个%d至%d的“随机数”是否为素数\n",
		0, RAND_MAX);
	
	srand(time(NULL));
	for (sum = i = 0; i < 1000000; i++)
	{
		t = rand();
		sum += isprime(t, pri);
	}
	printf("共统计出%d个素数\n用时:", sum);
	toc; printf("\n");
	
	tic; 	
	printf("效率测试:判断1百万个%d至%d的“随机数”是否为素数\n",
		_I32_MAX-RAND_MAX, _I32_MAX);
	
	srand(time(NULL));
	for (sum = i = 0; i < 1000000; i++)
	{
		t = _I32_MAX - rand();
		sum += isprime(t, pri);
	}
	printf("共统计出%d个素数\n用时:", sum);
	toc; printf("\n");
	return 0;
}

打表法判断素数_第2张图片

你可能感兴趣的:(素数判断)