<编程>比较两种素数表生成算法+计算程序运行时间+通过CMD重定向测试程序
最近学习加密算法,需要生成素数表,一开始使用简单的循环,从2开始判断。代码如下:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<vector> 5 #include<iterator> 6 #include<algorithm> 7 #include<ctime> 8 #include<cstring> 9 usingnamespace std; 10 bool isPrimeNumber(int num); 11 void judgePrimeNumber(int range,vector<int>&primeNumberList); 12 int main(void) 13 { 14 int range; 15 vector<int> primeNumberListJ; 16 while(cin){ 17 cin >> range; 18 judgePrimeNumber(range, primeNumberListJ); 19 for(unsignedint i =0; i < primeNumberListS.size(); i++) 20 cout << primeNumberListJ.at(i)<< endl; 21 primeNumberListJ.clear(); 22 } 23 return 0; 24 } 25 bool isPrimeNumber(int num) 26 { 27 if(num <2) 28 return false; 29 for(int i =2; i * i <= num; i++){ 30 if(num % i ==0) 31 return false; 32 } 33 return true; 34 } 35 void judgePrimeNumber(int range,vector<int>&primeNumberList) 36 { 37 for(int i =2; i <= range; i++) 38 if(isPrimeNumber(i)) 39 primeNumberList.push_back(i); 40 }
后来想起以前在学C语言的时候看过了叫筛选法的算法生成素数表。
筛选法又称筛法,具体做法是:先把N个自然数按次序排列起来。1不是质数,也不是合数,要划去。第二个数2是质数留下来,而把2后面所有能被2整除的数都划去。2后面第一个没划去的数是3,把3留下,再把3后面所有能被3整除的数都划去。3后面第一个没划去的数是5,把5留下,再把5后面所有能被5整除的数都划去。这样一直做下去,就会把不超过N的全部合数都筛掉,留下的就是不超过N的全部质数。
具体代码如下:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<vector> 5 #include<iterator> 6 #include<algorithm> 7 #include<ctime> 8 #include<cstring> 9 usingnamespace std; 10 bool isPrimeNumber(int num); 11 void selectPrimeNumber(int range,vector<int>&primeNumberList); 12 int main(void) 13 { 14 int range; 15 vector<int> primeNumberListS; 16 while(cin){ 17 cin >> range; 18 selectPrimeNumber(range, primeNumberListS); 19 primeNumberListS.clear(); 20 } 21 return 0; 22 } 23 bool isPrimeNumber(int num) 24 { 25 if(num <2) 26 return false; 27 for(int i =2; i * i <= num; i++){ 28 if(num % i ==0) 29 return false; 30 } 31 returntrue; 32 } 33 void selectPrimeNumber(int range,vector<int>&primeNumberList) 34 { 35 bool*numMap =newbool[range +1]; 36 memset(numMap,true,sizeof(bool)*(range +1)); 37 numMap[1]=false; 38 for(int i =2; i <= range;){ 39 while(!numMap[i]&& i <= range) 40 i++; 41 for(int j = i + i; j <= range; j += i){ 42 if(!numMap[j]) 43 continue; 44 numMap[j]=false; 45 } 46 i++; 47 } 48 for(int i =1; i <= range; i++) 49 if(numMap[i]) 50 primeNumberList.push_back(i); 51 delete[] numMap; 52 }
之后好奇心来了,筛选法到底比原来的方法高效了多少呢?
记得time.h里有有个clock()函数,可以返回程序运行到当前的时间,可以用它的计算两种算法的耗时。
具体代码如下:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<vector> 5 #include<iterator> 6 #include<algorithm> 7 #include<ctime> 8 #include<cstring> 9 usingnamespace std; 10 bool isPrimeNumber(int num); 11 void selectPrimeNumber(int range,vector<int>&primeNumberList); 12 void judgePrimeNumber(int range,vector<int>&primeNumberList); 13 int main(void) 14 { 15 int range; 16 vector<int> primeNumberListS; 17 vector<int> primeNumberListJ; 18 clock_t beginTime; 19 clock_t endTime; 20 while(cin){ 21 cin >> range; 22 beginTime = clock(); 23 selectPrimeNumber(range, primeNumberListS); 24 endTime = clock(); 25 cout <<"select Time: " 26 <<double(endTime - beginTime)/ CLOCKS_PER_SEC 27 << endl; 28 beginTime = clock(); 29 judgePrimeNumber(range, primeNumberListJ); 30 endTime = clock(); 31 cout <<"judge Time: " 32 <<double(endTime - beginTime)/ CLOCKS_PER_SEC 33 << endl; 34 primeNumberListS.clear(); 35 primeNumberListJ.clear(); 36 } 37 return0; 38 } 39 bool isPrimeNumber(int num) 40 { 41 if(num <2) 42 return false; 43 for(int i =2; i * i <= num; i++){ 44 if(num % i ==0) 45 return false; 46 } 47 return true; 48 } 49 void selectPrimeNumber(int range,vector<int>&primeNumberList) 50 { 51 bool*numMap =newbool[range +1]; 52 memset(numMap,true,sizeof(bool)*(range +1)); 53 numMap[1]=false; 54 for(int i =2; i <= range;){ 55 while(!numMap[i]&& i <= range) 56 i++; 57 for(int j = i + i; j <= range; j += i){ 58 if(!numMap[j]) 59 continue; 60 numMap[j]=false; 61 } 62 i++; 63 } 64 for(int i =1; i <= range; i++) 65 if(numMap[i]) 66 primeNumberList.push_back(i); 67 delete[] numMap; 68 } 69 void judgePrimeNumber(int range,vector<int>&primeNumberList) 70 { 71 for(int i =2; i <= range; i++) 72 if(isPrimeNumber(i)) 73 primeNumberList.push_back(i); 74 }
先输入100测试一下,结果如下:
应该是测试数据太小了,直接上10000吧:
会发现,但素数表越大,两者差距也越大。范围再大10倍的话,循环判断就卡了好就还没出时间。
最后额外的,在写程序的时候,经常要测试,当测试数据比较简短的时候可以手动输入。当测试数据比较多的时候,可以保存到txt文本文件中,放到测试程序的所在的目录下。
然后打开cmd命令,进入到测试程序所在的路径。
键入
coding.exe < in.txt
结果如下:
自动输入测试数据。
注意尖括号的方向。
另外一个方向的尖括号可以用于保存程序输出结果:
coding.exe > out.txt
在测试程序所在的目录下会自动生成out.txt。
最后的最后,一个高级的写法,从文件中读取输入,把结果输出到文件中:
type in.txt | coding.exe > out.txt
不上图,自行尝试。