零:素数
质数(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 }
注意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 }