题目:设计一个函数判断一个数是不是素数。
素数的概念:素数又称质数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数;否则称为合数。
这道题一共有三种思路,且运算效率依次提高。这三种算法唯一的变化是循环条件,我们可以看到从算法1到算法3判断一个数是不是素数的循环次数越来越少,这也代表算法效率越来越高。
int isPrime_1(unsigned int number)
{
if (number < 2)
return 0;
unsigned int div = 2;
while (div < number)
{
if (0 == number % div)
return 0;
div++;
}
return 1;
}
int isPrime_2(unsigned int number)
{
if (number < 2)
return 0;
unsigned int div = 2;
while (div < (number >> 1)) //此处用右移运算符代替除号,提高了运算效率(除法是效率最低的运算)
{
if (0 == number % div)
return 0;
div++;
}
return 1;
}
int isPrime_3(unsigned int number)
{
if (number < 2)
return 0;
unsigned int div = 2;
while (div*div <= number)
{
if (0 == number % div)
return 0;
div++;
}
return 1;
}
问:在第三种方案中,为什么判断一个数是不是素数只需要整除到其平方根就可以了?
答:因为一个合数一定可以由两个自然数相乘得到,并且这两个数一个大于或等于它的平方根,另一个小于或等于它的平方根。
因此只要小于或等于这个数开方的数(1除外)都不能整除这个数,那它一定数素数。
质数筛选方法——埃拉托斯特尼筛法
埃拉托斯特尼筛法,简称埃氏 或爱氏筛,是一种由希腊数学家埃拉托斯特尼所提出的一种简单检定素数的算法。要得到自然数n以内的全部素数,必须把不大于根号n的所有素数的倍数剔除,剩下的就是素数。题目:请输出160000以内的所有素数。
解题思路:当所求素数数量过多时我们不管用以上哪种方法,效率都是特别慢的,因为每个数都要用多个数来整除它。在这我们采用埃拉托斯特尼筛法。
1. 先得到160000的开方4000。
2. 去除了所有素数的倍数。从2开始筛选,去除2到160000之间所有2的倍数。
3.去除3到160000之间所有3的倍数。
4. 一直循环,直到4000。去了所有质数的倍数,最后剩下的都是素数。
< code >
int main()
{
int num = 160000;
int sq = sqrt(num*1.0);
bool *isPrime = new bool[num + 1];
//初始化:默认所有元素均为素数
for (int i = 2; i< num + 1; i++)
{
isPrime[i] = true;
}
for (int i = 2; i <= sq; i++)
{
if (isPrime[i] == true)
{
for (int j = 2; j < num + 1; j++)
{
if (i*j < num + 1)
{
isPrime[i*j] = false;
}
}
}
}
for (int j = 2; j < num + 1; j++)
{
if (isPrime[j] == true)
{
printf("%d ", j);
}
}
delete[]isPrime;
system("pause");
return 0;
}