质数定义:
为在大于1的自然数中,除了1和它本身以外不再有其他因数。
意思就是:质数除了1和他本身除以谁也除不尽Σ(っ °Д °;)っ
知道了定义,就可以求质数
方法一
既然质数是除以谁也除不尽,那就把一个数X,除以所有的比他小的数,结果要是都除不尽,这个数就是质数。
void yi()
{
//求100以内的所有质数,计算i是否为质数
for (int i = 2; i < 100; i++)
{
int sign = 0; //当i被某一个数除尽的时候,sign变成1
int sq = sqrt(i);
//循环除以所有的比2大的数,比自己小的数
for (int j = 2; j <= sq; j++)
{
//有一个,能被i整除,例如 18%3==0,则18不是质数
if (i%j == 0) { sign = 1; break; }
}
if(sign==0)
cout << "质数:" << i << endl;
}
}
比较慢的程序,不改变思想,可以降低速度,就是
循环除以所有的比2大的数,比自己小的数
改为
循环除以所有的比2大的数,比sqrt(x)小的数
可以提前判断这个数是素数,省下好多判断
for (int j = 2; j <= i; j++)
{
//有一个,能被i整除,例如 18%3==0,则18不是质数
if (i%j == 0) sign=1;
}
改为
--
int sq=sqrt(x);
for (int j = 2; j <= sq; j++)
{
//有一个,能被i整除,例如 18%3==0,则18不是质数
if (i%j == 0) sign=1;
}
直接上线性求素数
思想是:任何一个数乘素数,都不是一个素数,用数组arr依次存素数,
在依次计算出来i是否是质数,之后,用i乘以所有的已经求出来的素数
例如当 i=10时
质数有 2 3 5 7
标记
10*2=20
30
50
70
都是合数
然后在数组check中标记 20 30 50 70都是和数
注意:不要把 ( 合数*求出的每个素数 ) 这样会导致重复标记一个数为合数
只需要
这个算法可以一下子求出大量素数,例如前一万个
但是如果判断某个是否为素数,则就比较麻烦了。
算法:判断i是不是素数
基本的数据
求前十万个素数
数组要开到
int const IMAX = 1300000;
int arr[IMAX + 100]{ 0 }; //依次存放求出来的素数
bool arr2[IMAX * 10 + 100]{ 0 }; //素数的倍数不是素数,不是素数的标记为1
就够用了
前十万个素数—> 要计算前一百三十万的数
第一万个素数—>要计算前104729个
//基本的循环除法
int division(int IMAX)
{
int sign = 0;
int sq = 0;
int num = 0;
for (int x = 2; x <= IMAX; x++)
{
sq = sqrt(x);
sign = 0;
for (int y = 2; y <= sq; y++)
{
//有一个,能被i整除,例如 18%3==0,则18不是质数
if (x % y == 0) { sign = 1; break; }
}
if (sign == 0) { num++; }
}
cout << "一共有素数" << num << endl;
return 0;
}
//线性素数法
int const ARR_MAX = 10000000*10; //数组开到arr_max最大可以求ARR_MAX之间的所有素数 一亿以内的素数
int arr[ARR_MAX + 100]{ 0 }; //依次存放求出来的素数
bool arr2[ARR_MAX + 100]{ 0 }; //素数的倍数不是素数,不是素数的标记为1
int LinearPrimeNumbers(int IMAX)
{
int tot = 0; //记录素数的数量
//从2开始循环判断每个数是否是素数
for (int i = 2; i<IMAX; i++)
{
//在arr2[]数组中没有被标记的 i 则是素数
if (arr2[i] == 0)
{
//把素数存入arr数组中
arr[tot] = i;
//素数总和加1 输出
tot++;
//cout << i << endl;
}
//
for (int j = 0; j<tot; j++)
{
//要标记的数,超出要计算的最大值,跳出
if ( arr[j] * i > IMAX ) break;
//标记为合数
arr2[arr[j] * i] = 1;
//要是i可以被一个质数整除,则跳出,不再进行其余的剩下的质数*i进行标记
//目的是为了防止重复标记
if ( i % arr[j] == 0) break;
}
}
cout << "线性法素数有" << tot << endl;
return 0;
}
int main()
{
int IMAX = 5000000*10;
clock_t cbegin = clock();
PrimeNumbers::LinearPrimeNumbers(IMAX);
clock_t cend = clock();
cout << "计算"<<IMAX << "以内的素数 线性素数筛用时:" << double(cend - cbegin) / CLOCKS_PER_SEC << endl;
cbegin = clock();
PrimeNumbers::division(IMAX);
cend = clock();
cout << "计算" << IMAX << "以内的素数 循环除法用时:" << double(cend - cbegin) / CLOCKS_PER_SEC << endl;
return 0;
}
速度对比差距还是非常大的
线性法素数有3001134
计算50000000以内的素数 线性素数筛用时:0.495
一共有素数3001134
计算50000000以内的素数 循环除法用时:72.618
请按任意键继续. . .