素数

零:素数

  质数(prime number)又称素数,有无限个。一个大于1的自然数,除了1和它本身外,不能被其他自然数整除(除0以外)的数称之为素数(质数);否则称为合数。




一:最基本的素数判定

  先求开方,避免溢出. 开方注意四舍五入 floor(XX + 0.5):


#include <iostream> #include <cmath> bool is_prime(int x) //是否是素数 { if(x<=1) return false; int mid=floor(sqrt(x)+0.5); //找到中间的那个数,注意这里的四舍五入, 用到 floor(**+0.5) for (int i=2;i<=mid;i++) //要是这里用 i*i<=x 的话可能溢出!!! { if (!(x%i)) { return false; //不是 } } return true; } int main(void) { for (int i=0;i<100;i++) { std::cout<<i<<"is prime: "<<is_prime(i)<<"\n"; } std::cin.get(); return 0; }



二:筛选法与素数表

  上面的方法是一个一个地判断,如果要判断从2到20000的这么多怎么提高效率?这里用筛选法,思想是:先预处理一个有N个数字的bool数组isPrime[N],下标n对应的数组值表明整数n是不是一个素数。这样只要预处理一次,以后直接取即可。

  如何预处理:从2开始依次遍历直到sqrt(N),如果 isPrime[n] == true,则对于小于N的n的二三四五等整数倍的数m,isPrime[m] = false。其实这里就是把从2开始的数字的大于1的整数倍的数都设置成不是,是那些数倍数的数字肯定不是素数了嘛。

 1 #include <iostream>
 2 #include <cmath>
 3 
 4 using std::sqrt;
 5 using std::cout;
 6 using std::cin;
 7 using std::endl;
 8 
 9 const int N = 160;
10 bool isPrime[N];
11 
12 void setPrime(void)
13 {
14     memset(isPrime, true, sizeof(isPrime));        //刚开始设置为都是素数
15     int mid = floor(sqrt(double(N)) + 0.5);
16 
17     for (int i = 2; i <= mid; i++)
18     {
19         if(isPrime[i])        //注意这个判断!!!如果没有这个判断的话,也可以,但做了很多重复的计算
20         {
21             int miltiple = 2;
22             while(i * miltiple < N)
23             {
24                 isPrime[i * miltiple] = false;        //设置不是素数的
25                 miltiple++;
26             }
27         }    
28     }
29 }
30 
31 void show(void)
32 {
33     for (int i = 2; i < N; i++)
34     {
35         cout << i;
36         if(isPrime[i])
37             cout << " is prime";
38         else
39             cout << " is not prime";
40         cout<<endl;
41     }
42 }
43 
44 int main(void)
45 {
46     setPrime();
47     show();
48     cin.get();
49 }
View Code

注意22行的while循环:

//初始化都是素数标志都是true,那么在后面的for循环中,如果遇到一个数A是false,
//那么A的false一定是因为数字A是前面某个数B的倍数,既然如此,对于数A来说,
//A的一二三四倍都是数B的某个倍数,也就是说已经被数B设置过了,所以A不需要再设置



三:节省空间

  上面用bool数组太浪费了,bool也不是一个位,为了用一个bit表示是不是素数,我们用 bitset ,这样就节省了。

 1 #include <iostream>
 2 #include <cmath>
 3 #include <bitset>
 4 
 5 using std::sqrt;
 6 using std::cout;
 7 using std::cin;
 8 using std::endl;
 9 using std::bitset;
10 
11 const int N = 160;
12 bitset<N> isPrime(true);
13 
14 
15 void setPrime(void)
16 {
17     int mid = floor(sqrt(double(N)) + 0.5);
18 
19     for (int i = 2; i <= mid; i++)
20     {
21         if(isPrime[i])        //注意这个判断!!!如果没有这个判断的话,也可以,但做了很多重复的计算
22         {
23             int miltiple = 2;
24             while(i * miltiple < N)
25             {
26                 isPrime[i * miltiple] = false;        //设置不是素数的
27                 miltiple++;
28             }
29         }    
30     }
31 }
32 
33 void show(void)
34 {
35     for (int i = 2; i < N; i++)
36     {
37         cout << i;
38         if(isPrime[i])
39             cout << " is prime";
40         else
41             cout << " is not prime";
42         cout<<endl;
43     }
44 }
45 
46 int main(void)
47 {
48     setPrime();
49     show();
50     cin.get();
51 }
View Code
原文地址:https://www.cnblogs.com/jiayith/p/2997017.html