1.素数的定义
素数就是质数,有无限个。除了1和该数本身以外不再有其他的因数的数被称为素数,比如2=1×2;5=1×5;23=1×23;……所以2、5和23就是素数。值得注意的是,0 与 1 既不是素数,也不是合数。
2.素数的求解方法
1.直接求解:
我们如何用程序判断一个数是不是素数呢?(比如设这个数为i)最简单的方法3.就是,用这个数i去整除2~i-1;比如判断10,是不是素数, 1 2 3 4 5 6 7 8 9 10;,我们就可以用10去试除2-9,如果其中存在能把10整除的数,比如5,那么10就不是素数,如果没有能把10整除的数,那么10就是素数。
附上源码大家体验效果:
int main()
{
int i = 0;
printf("请输入你想要判断的数:\n");
scanf("%d", &i);
int j = 0;
for (j = 2; j < i; j++)
{
if (i % j == 0)
break;
}
if (i == j)
{
printf("%d是素数\n",i);
}
else
{
printf("%d不是素数\n",i);
}
return 0;
}
3.试除法优化思路
引入另外一个例子,我们已经知道了如何求解素数,那么,我们可以编写一个函数来判断一下 100-200之间有多少个素数吗?再打印出来。
思路:
我们首先应该产生100-200之间的数字,外层for循环可以搞定
然后用第二个循环遍历第一个循环产生的数字2~i-1,来判断他是不是素数,是就答应并且计数。
附上源码大家体验效果:
int main()
{
int i = 0;
int count = 0;
// 外层循环用来获取100~200之间的所有数据,100肯定不是素数,因此i从101开始
for (i = 101; i <= 200; i++)
{
//判断i是否为素数:用[2, i)之间的每个数据去被i除,只要有一个可以被整除,则不是素数
int j = 0;
for (j = 2; j < i; j++)
{
if (i % j == 0)
{
break;
}
}
// 上述循环结束之后,如果j和i相等,说明[2, i)之间的所有数据都不能被i整除,则i为素数
if (j == i)
{
count++;
printf("%d ", i);
}
}
printf("\ncount = %d\n", count);
return 0;
}
但是,我们想一下:
1.100到200之间的数字,我们都要遍历一遍,有必要吗?
我们知道的,偶数一定不是素数,所以在外层循环我们就没有必要再产生偶数
可以将外层循环控制条件i++改成i+=2,每次产生顺序奇数。
2.对于内层循环的一个功能,我们就是去遍历找外层循环产生的数字i的因子嘛,那我们来看一下:
如果 i= 9 9 = 1*9 9 = 3*3 9开平方 = 3
i = 16 16 = 1*16=2*8= 4*4 16开平发 = 4
i = 8 8 = 1*8 = 2*4 8开平方>2
那我们总结一个规律,一个数的因子中除了1,只要能被整除,有一个因子一定小于这个数的开平方。那我的内层循环就可以改为:j<i -> j<sqrt(i)
补充:sqrt()库函数,用于求一个数的开平方
头文件 math.h
优化:
int main()
{
int i = 0;
int count = 0;
// 外层循环用来获取100~200之间的所有数据,100肯定不是素数,因此i从101开始
for (i = 101; i <= 200; i+=2)
{
//判断i是否为素数:用[2, i)之间的每个数据去被i除,只要有一个可以被整除,则不是素数
int j = 0;
for (j = 2; j <=sqrt(i); j++)
{
if (i % j == 0)
{
break;
}
}
// 上述循环结束之后,如果j和i相等,说明[2, i)之间的所有数据都不能被i整除,则i为素数
if (j > sqrt(i))
{
count++;
printf("%d ", i);
}
}
printf("\ncount = %d\n", count);
return 0;
}
虽然运行结果是一样的,但是当我们要判断100-200之间的数是否有素数的时候,只用判断一半数据,而且更舒服的是对于内层循环来说,当要判断像100这种数据是不是素数,就不用遍历2——99,只用遍历1——9,做到了指数层级别的优化。非常nice。