大一剛剛結束,回過頭髮現自己這一年太浪了,基本沒學什麼東西,所以下定決心從頭開始
那就說一下這最簡單又不簡單的質數問題吧
我們要求某個範圍內的所有質數,當然最基本最重要的方法就是除一個數取餘數在判斷是否爲0
一、最簡單的粗暴的窮舉法
#include<iostream>
#include<math.h>
#include<time.h>
#define max 100
using namespace std;
void main() {
clock_t start, end;
start = clock();
int * prime = (int*)malloc(sizeof(int)*max);//記錄所有素數的數組
int count = 1;//素數的個數
*prime = 2;//初值
for (int i = 3; i <= max; ++i) {
bool choice = true;//假設爲質數
for (int j = 2; j <i; ++j) {
if (i%j == 0) {//不是質數
choice = false;
break;
}
}
if (choice) {
*(prime + count) = i;
count++;
}
}
free(prime);//釋放素數的數組指針,避免內存泄漏
end = clock();
float time = (float)(end - start) / 1000;
cout << "time is " << time << "s" << endl;
cout << "count is " << count << endl;
system("pause");
}
二、循環範圍由2~i-1變成2~sqrt(i)
至於爲什麼是sqrt(i)自己思考吧,數學問題
#include<iostream>
#include<math.h>
#include<time.h>
#define max 100
using namespace std;
void main() {
clock_t start, end;
start = clock();
int * prime = (int*)malloc(sizeof(int)*max);//記錄所有素數的數組
int count = 1;//素數的個數
*prime = 2;//初值
for (int i = 3; i <= max; ++i) {
bool choice = true;//假設爲質數
for (int j = 2; j <=sqrt(i); ++j) {
if (i%j == 0) {//不是質數
choice = false;
break;
}
}
if (choice) {
*(prime + count) = i;
count++;
}
}
for (int i = 0; i < count; ++i) {
cout << prime[i] << endl;
}
free(prime);//釋放素數的數組指針,避免內存泄漏
end = clock();
float time = (float)(end - start) / 1000;
cout << "time is " << time << "s" << endl;
cout << "count is " << count << endl;
system("pause");
}
三、我們發現每次循環都調用sqrt函數比較慢,所以先把這個數賦給k,直接調用k就好了
#include<iostream>
#include<math.h>
#include<time.h>
#define max 10000000
using namespace std;
void main() {
clock_t start, end;
start = clock();
int * prime = (int*)malloc(sizeof(int)*max);//記錄所有素數的數組
int count = 1;//素數的個數
*prime = 2;//初值
for (int i = 3; i <= max; ++i) {
bool choice = true;//假設爲質數
int k = sqrt(i);
for (int j = 2; j <= k ; ++j) {
if (i%j == 0) {//不是質數
choice = false;
break;
}
}
if (choice) {
*(prime + count) = i;
count++;
}
}
free(prime);//釋放素數的數組指針,避免內存泄漏
end = clock();
float time = (float)(end - start)/1000;
cout << "time is " << time <<"s"<< endl;
cout << "count is " << count << endl;
system("pause");
}
四、這步優化相對困難。我們知道,所有合數都能寫成若干素數相乘的形式,故判斷i數i是否爲質數,只需要用i除以從2到sqrt(i)之間的質數就可以,不需要除以這個區間的合數。但是問題出現了,我們要記錄所有小於i的質數,這就要用堆內存建立一個整型數組,數組長度爲max(我在考慮是不是可以建一個更小點的,,,算了,比較懶,不想了)用來保存所有已經求過的質數,這步的關鍵還有就是默認好2是第一個質數。
#include<iostream>
#include<math.h>
#include<time.h>
#define max 100000000
using namespace std;
void main() {
clock_t start, end;
start = clock();
int * prime =(int*) malloc(sizeof(int)*max);//記錄所有素數的數組
int count = 1;//素數的個數
*prime = 2;//初值
int tempmax = 0;//小於sqrt(i)的最大素數下標
for (int i = 3; i <= max; ++i) {
bool choice = true;//假設爲質數
int k = sqrt(i) + 1;
for (int j = 0; j <=tempmax; ++j) {
if(prime[tempmax] < k)tempmax++;
if (i % prime[j] == 0) {//不是質數
choice = false;
break;
}
}
if (choice) {//是質數
*(prime + count) = i;
count++;
}
}
//for (int i = 0; i < count; ++i) {
// cout << i<<" "<<prime[i] << endl;
//}
free(prime);//釋放素數的數組指針,避免內存泄漏
end = clock();
float time = (float)(end - start) / 1000;
cout << "time is " << time << "s" << endl;
cout << "count is " << count << endl;
system("pause");
}
這點東西做了一上午,哎,真是鹹魚。。。大二重新做人吧
關於速度的結果如下,可以看到每一步的優化是有效果的,而且在求較大範圍的質數時更加明顯
本文章可能存在很多不足,請多指點
2017 / 7 / 7