Cプログラミング
 Computer >> コンピューター >  >> プログラミング >> Cプログラミング

ウィルソンの定理を使ってn未満の素数をすべて効率的に生成する方法

本記事では、nより小さいすべての素数を効率的に生成する方法を紹介します。このアプローチではウィルソンの定理(Wilson's theorem)を活用します。ウィルソンの定理によれば、ある数kが素数であるとき、((k - 1)! + 1) mod k の計算結果は必ず0になります。つまり、この性質を利用することで、素数判定を行うことができるのです。

ただし、この手法には注意点があります。CやC++のような言語でそのまま実装すると、階乗の計算によって非常に大きな数が生じるため、標準の整数型では大きな整数を扱えず、正しく動作しません。実際に使用する場合は、多倍長整数(ビッグナンバー)ライブラリの導入や、オーバーフロー対策が必要になります。

アルゴリズム

genAllPrime(n)

Begin
    fact := 1
    for i in range 2 to n-1, do
        fact := fact * (i - 1)
        if (fact + 1) mod i is 0, then
            print i
        end if
    done
End

C++での実装例

以下は、上記のアルゴリズムをC++で実装した例です。ここでは説明のためint型を使用していますが、前述の通り大きなnに対してはオーバーフローが発生する点に留意してください。

#include <iostream>
using namespace std;
void genAllPrimes(int n){
    int fact = 1;
    for(int i=2;i<n;i++){
        fact = fact * (i - 1);
        if ((fact + 1) % i == 0){
            cout<< i << " ";
        }
    }
}
int main() {
    int n = 10;
    genAllPrimes(n);
}

出力結果

2 3 5 7

n = 10 を指定した場合、10未満の素数である「2、3、5、7」が出力されます。

まとめ

ウィルソンの定理を用いた素数生成は、数学的に非常にエレガントなアプローチです。しかし、階乗の計算コストが大きく、数値も急激に膨らむため、実用面ではエラトステネスの篩(ふるい)などの手法の方が一般的に高速かつ効率的とされています。理論的な興味深さと実用性の両面から、両者の違いを理解しておくと良いでしょう。

  1. 【C++】配列内のすべての素数の積を求める方法

    整数型配列 arr[] が与えられたとき、その配列に含まれるすべての素数を見つけ出し、それらの積を計算するのが本記事のテーマです。素数とは、1とその数自身でしか割り切れない正の整数のことです。たとえば、2、3、5、7、11などが素数に該当します。それでは、次の配列を例に解を求めてみましょう。入力: arr[] = { 11, 20, 31, 4, 5, 6, 70 }出力: 1705説明: 配列内の素数は 11、31、5 の3つであり、その積は 11 × 31 × 5 = 1705 となります。入力: arr[] = { 1, 2, 3, 4, 5, 6, 7 }出力: 210説明: 配列内の

  2. 指定した範囲内のすべての素数を出力するPythonプログラム

    この記事では、以下の問題文に対する解決方法について学んでいきます。 問題文 ある区間が与えられたとき、その範囲内に含まれるすべての素数を求めて出力する必要があります。 ここでは、素数の基本的な定義に基づいた全探索(ブルートフォース)によるアプローチを紹介します。素数とは、「1とその数自身のみを約数として持ち、それ以外の数を約数に持たない自然数」のことです。 この定義に基づき、各数値が素数の条件を満たしているかどうかを判定し、条件が真(True)と評価されるたびに出力処理を行います。 それでは、実際の実装例を見ていきましょう。 実装例 start = 1 end = 37 for val in