(C ++コードを含む)素数の概要を決定するいくつかの方法
素数が定義されています
素数としても知られている(素数)、素数は、番号1は、それ自身の性質および1よりも数因子大きいに指します。29 2〜29の唯一の要因である素数である;例えば、素数は、二つの唯一の要因である2、1及び2で51は素数ではない、1及び51 3及び17に加えて、それは、2つの要因があるので、その51ある合成数。
二、素数判断方法
正の整数n(≧2)与えられました:
方法1.定義
残りはその後オペランドがので、数Nの要因であること、ということ0でnは素数でない場合は、Nで割った、程度である[2、N-1]のすべての整数の。コードは以下の通りであります:
bool isPrime(int n){
bool yes=true;
for(int i=2;i<n;i++){
if(n%i==0){
yes=false;
break;
}
}
return yes;
}
向上のためのメソッドを定義します。2.
因子以来N常にペアで現れ、1〔に分布しています、 ]と[ 、N]の範囲(数Ruoyin 2つのリピート因子として私たちは)、我々は唯一の範囲を決定する必要があります。コードは以下の通りであります:
bool isPrime2(int n){
bool yes=true;
for(int i=2;i<=sqrt(n);i++){
if(n%i==0){
yes=false;
break;
}
}
return yes;
}
3.メソッドを法
nの式場合n≥6が、N、次に、6X + 1,6x + 2,6x + 3,6x + 4,6x + 5,6x(X≧1)中のように表すことができるので、場合6X + 2,6x + 4または6X、Nは素数ではないことは明らかである; nは6×+ 1発現または6X + 5である場合、したがって、それは素数、次いで、塗布法もよいです。コードは以下の通りであります:
bool isPrime3(int n){
bool yes=false;
if(n==2||n==3||n==5){ //当n<6时列举即可
yes=true;
}
else if(n%6==1||n%6==5){ //通过判断余数的方式来判断n的表达式
yes=true;
for(int i=2;i<=sqrt(n);i++){
if(n%i==0){
yes=false;
break;
}
}
}
return yes;
}
テスト、時間を消費
### 4.筛选法(Eratosthenes筛选)
我们可以很容易的判断出2、3、5等较简单的数是素数,而且,当一个数是素数后,它的倍数一定为合数。因此,我们可以将一定范围的整数筛选掉合数,剩下的即是素数。代码如下:
```cpp
bool isPrime4(int n){
bool yes=false;
//先生成一定范围的整数表,再应用筛选法,得到素数表,最后与素数表比对
//生成0~100000内的素数表
int num[100000]={0}; //0表示素数,1表示合数
for(int i=2;i<100000;i++){
if(!num[i]){
for(int j=i+i;j<100000;j+=i){
num[j]=1;
}
}
}
if(!num[n]){
yes=true;
}
return yes;
}
5.改善されたスクリーニング
まず第一に、私たちは必ず2を除くすべての素数は奇数であることをすることができ、それは、奇数列2よりも大きいの手段を確立することが可能であるので、両方の判断を拡大するだけでなく、裁判官の数を減らすこと、及び、その後、我々は3、5の奇数列を取得し、 7,9 ......、一例として図3に示すように、この方法によれば、我々は、選別されるべきである4 3×2,3×3,3×4 ......が、3×2,3×4 ......偶数である場合、選別された、及び5の倍数をスクリーニングする際にこのようのみ、3×3,3×5,3×7アウト画面、3×3から始まる......、同じ5×2で始めるべきであるが、5×2,5×4 ...... 5×7,5×9を選別するので、スクリーニングは5×5の5の倍数でなければなりません、でも、あなたは5×3、5×3から始めて検討する必要がありますが、すでに3の倍数を遮蔽でふるい始めています私たちは、フィルタグループの数を観察するとき......、などAルールがあります:素数ならば、アウト×、画面からフィルタが開始さ×+ 2×A× I(私は0,1 =、 2 ......)。
開始画面から×理由:4我々は×2を選別しなければならない方法によって、×3、 ×4 ...... ×2、×4 ......偶数、選別されたされ、そしてAから3の倍数をスクリーニングする場合、開始×3フィルタは、> 3は、確かに、この3×数で選別された場合と、その後、フィルタは×5、同じトークン、起動した場合は> 5、その後、フィルタ5 ×スクリーニング始まりそうになるまで、それが選別される前に処理されませんでした。倍数は5×のこの数を選別されたとき。
なぜ画面アウト×+ 2×A× I(iは0,1,2 ...... =)?私たちは、変換式を見ることができます:×+ 2× ××私は(+ 2×i)を=。スクリーニングは、×(+ 0)×うち、画面から起動時ことが分かる ×(+ 2)×(+ 4)...... 前の手順の法律に沿っ。
上記のプロセスは、コードのように要約されます:
bool isPrime5(int n){
bool yes=false;
int num[100000]={0}; //生成3~2*99999+3范围内的奇数数组
//先判断当n=2时的情况
if(n==2){
yes=true;
}
else{
for(int i=0;i<100000;i++){
if(!num[i]){
for(int j=(2*i+3)*(2*i+3);j<(2*100000+3);j+=2*(2*i+3)){
num[(j-3)/2]=1;
}
}
}
}
if((n-3)%2==0){
if(!num[(n-3)/2]){
yes=true;
}
}
return yes;
}
第三に、要約
次のように上記の方法は、一緒に入れています。
#include <iostream>
#include <math.h>
#include <time.h>
#define SIZE 10000
using namespace std;
bool isPrime(int n) {
bool yes = true;
for (int i = 2; i < n; i++) {
if (n % i == 0) {
yes = false;
break;
}
}
return yes;
}
bool isPrime2(int n) {
bool yes = true;
for (int i = 2; i <= sqrt(n); i++) {
if (n % i == 0) {
yes = false;
break;
}
}
return yes;
}
bool isPrime3(int n) {
bool yes = false;
if (n == 2 || n == 3 || n == 5) {
yes = true;
}
else if(n%6==1||n%6==5) {
yes = true;
for (int i = 2; i <= sqrt(n); i++) {
if (n % i == 0) {
yes = false;
break;
}
}
}
return yes;
}
bool isPrime4(int n) {
bool yes = false;
int num[SIZE] = { 0 };
for (int i = 2; i < SIZE; i++) {
if (!num[i]) {
for (int j = i + i; j < SIZE; j += i) {
num[j] = 1;
}
}
}
if (!num[n]) {
yes = true;
}
return yes;
}
bool isPrime5(int n) {
bool yes = false;
int num[SIZE] = { 0 };
if (n == 2) {
yes = true;
}
else {
for (int i = 0; i < SIZE; i++) {
if (!num[i]) {
for (int j = (2 * i + 3) * (2 * i + 3); j < (2 * SIZE + 3); j += 2 * (2 * i + 3)) {
num[(j - 3) / 2] = 1;
}
}
}
}
if ((n - 3) % 2 == 0) {
if (!num[(n - 3) / 2]) {
yes = true;
}
}
return yes;
}
int main() {
cout << "function isPrime():" << endl;
time_t before = clock();
for (int i = 2, j = 0; i < 10000; i++) {
if (isPrime(i)) {
cout << i << " ";
j++;
}
if (j == 9) {
cout << endl;
j = 0;
}
}
time_t after = clock();
cout << endl;
cout << static_cast<double>((after - before) * 1000 / CLOCKS_PER_SEC) << "(ms)" << endl;
cout << "function isPrime2():" << endl;
before = clock();
for (int i = 2, j = 0; i < 10000; i++) {
if (isPrime2(i)) {
cout << i << " ";
j++;
}
if (j == 9) {
cout << endl;
j = 0;
}
}
after = clock();
cout << endl;
cout << static_cast<double>((after - before) * 1000 / CLOCKS_PER_SEC) << "(ms)" << endl;
cout << "function isPrime3():" << endl;
before = clock();
for (int i = 2, j = 0; i < 10000; i++) {
if (isPrime3(i)) {
cout << i << " ";
j++;
}
if (j == 9) {
cout << endl;
j = 0;
}
}
after = clock();
cout << endl;
cout << static_cast<double>((after - before) * 1000 / CLOCKS_PER_SEC) << "(ms)" << endl;
cout << "function isPrime4():" << endl;
before = clock();
for (int i = 2, j = 0; i < 10000; i++) {
if (isPrime4(i)) {
cout << i << " ";
j++;
}
if (j == 9) {
cout << endl;
j = 0;
}
}
after = clock();
cout << endl;
cout << static_cast<double>((after - before) * 1000 / CLOCKS_PER_SEC) << "(ms)" << endl;
cout << "function isPrime5():" << endl;
before = clock();
for (int i = 2, j = 0; i < 10000; i++) {
if (isPrime5(i)) {
cout << i << " ";
j++;
}
if (j == 9) {
cout << endl;
j = 0;
}
}
after = clock();
cout << endl;
cout << static_cast<double>((after - before) * 1000 / CLOCKS_PER_SEC) << "(ms)" << endl;
return 0;
}
私たちは、コード(動作環境:vs2019、デバッグ、x64の)を実行します、時間のかかる結果は次の通りです
isPrimeは():379ms
370ms:isPrime2()
isPrime3を():400msの
1008ms:isPrime4()
isPrime5を():1028ms
プロセスの発見効率を2最高。Iが最適化されるコードであってもよい、方法3の効率が高くありません。方法4と5氏とテーブルの方法は、消費時間が増加し、素数である必要があり、その後、比較すること。表は、素数を生成することである場合、整数が素数か否かが判定され、二つの方法の効率は比較的高くてもよいです。前記大きな素数テーブルの範囲を生成する方法。