关于求素数
1.问题描述
质数又称素数,有无限个。一个大于1的自然数,除了1和它本身外,不能被其他自然数整除,换句话说就是该数除了1和它本身以外不再有其他的因数;否则称为合数。然后我们可以选择一个输入范围,例如输入start=100和end=200,然后求出之间所有的素数。
2.解题思路
首先呢我们求素数,肯定要用的 for 这个关键字,对这个程序而言,肯定需要用的双层循环来实现。
外层循环先对我们的 start 到 end 之间的每一个数进行迭代,用变量 i 来表示,显然i的取值范围是"strat <= i <= end",逐个对其进行检测是否为素数,
内层循环则依然是对从 strat 到 i 之间的每一个数进行迭代,用 k 依次去除需要判定的整数 i (很明显k的取值范围是2~i) 。如果 i 能被 k 整除的话 ,则表明 i 不是素数,反之则证明是素数。
代码如下:
#include<stdio.h>
#include<math.h>
#include<Windows.h>
int main()
{
int start = 0;
int end = 0;
int i = 0;
int count = 0; //对素数的个数进行计数
printf("输入 START 和 END:");
scanf_s("%d %d", &start, &end);
for (i=start; i<= end; i++) //对start ~end的每个数进行判断
{
int k = 0;
for (k = 2; k < i; k++)
{
if (i%k == 0) //若取余为零,说明不是素数,跳出对该数判断的循环。
break;
}
if (k == i) //要判断的数已经和小于自身的数(不包括1和它本身)全部比较了,均不满足以上条件,说明该数是素数。
{
printf("%d ",i);
count++;
}
}
printf("\n一共有%d个素数", count);
system("pause");
return 0;
}
当然,这只不过是我们最基础的方法,我还能不能把代码进行优化呢?
答案是肯定的,我们可以想到,这些数字中有偶数和奇数之分,偶数当然就不用考虑了,他们肯定不是素数,这样我们就节省了一半的工作量
新代码如下:
#include<stdio.h>
#include<math.h>
#include<Windows.h>
int main()
{
int start = 0;
int end = 0;
int i = 0;
int count = 0; //对素数的个数进行计数
printf("输入 START 和 END:");
scanf_s("%d %d", &start, &end);
if (start % 2 == 0)
i = start+1;
else
i = start ;
for (i ; i <= end; i+=2) //对start ~end的每个奇数进行判断
{
int k = 0;
for (k = 2; k < i; k++)
{
if (i%k == 0) //若取余为零,说明不是素数,跳出对该数判断的循环。
break;
}
if (k == i) //要判断的数已经和小于自身的数(不包括1和它本身)全部比较了,均不满足以上条件,说明该数是素数。
{
printf("%d ", i);
count++;
}
}
printf("\n一共有%d个素数", count);
system("pause");
return 0;
}
关于判断一个具体的数(比如200)是否是素数,不用试除到199。因为任何一个数都可以写成两个数的乘积的形式,由于我们是从2开始试除的,所以2是试除的第一个判断条件。若被2整除,以200为例,即200/2=100,可知100就是试除的极限值,当我们试除的数超过100时,一定是一个小于2的数和试除的数相乘才等于200。
换种说法来讲,2是一个数的次小因数,k/2是这个数的次大因数。所以判断条件可以改为for (k=2; k < i/2; k++); 相对应的,后面的if语句也要做出调整 if (k == i/2) ;
更近一步来说,num/2也不是最佳的试除极限。num的算术平方根才是最佳试除极限,所以判断语句改为 for (k = 2; i <=sqrt(i);k++); if语句改为 if (k >sqrt(i) ) ;
所以更完美的代码如下:
#include<stdio.h>
#include<math.h>
#include<Windows.h>
int main()
{
int start = 0;
int end = 0;
int i = 0;
int count = 0; //对素数的个数进行计数
printf("输入 START 和 END:");
scanf_s("%d %d", &start, &end);
if (start % 2 == 0)
i = start+1;
else
i = start ;
for (i ; i <= end; i+=2) //对start ~end的每个奇数进行判断
{
int k = 0;
for (k = 2; k <= sqrt(i); k++) //比较范围是从2到自身的算术平方根的值
{
if (i%k == 0) //若取余为零,说明不是素数,跳出对该数判断的循环。
break;
}
if (k >sqrt(i)) //注意判断条件,从2到根号下num 都不能整除,说明该数是素数。
{
printf("%d ", i);
count++;
}
}
printf("\n一共有%d个素数", count);
system("pause");
return 0;
}
好了,对于for的学习到这就结束了,如果还有优化或者改正的地方,希望大家多多指教