【プログラム】素数を求める ~エラトステネスのふるい~

素数(Initial number)とは

 * 1より大きい整数の内、1と自分自身以外の整数では割り切れないような整数をいう(1は含まない)

■ サンプル

例1:普通に求める

SampleInitialNumber1.java
public class SampleInitialNumber1 {
   public static void main(String[] args) {
      long start = System.currentTimeMillis();
      // 0 - 100000までの素数を出力する
      int num = 100000;
      // 除算の回数
      int counter = 0;
      // 素数の数をカウント
      int initialCount = 0;
      for (int i = 2; i <= num; i++) {
         int j;
         for (j = 2; j < i; j++) {
            counter++;
            if (i % j == 0) {
               // 割り切れると素数ではなく、それ以上の繰返しは不要
               break;
            }
         }
         if (i == j) {
            // 最後まで割り切れなかった
            initialCount++;
            System.out.println(i);
         }
      }
      System.out.println("素数の数:" + initialCount);
      System.out.println("除算を行った回数:" + counter);
      long stop = System.currentTimeMillis();
      System.out.println("実行時間 : " + (stop - start) + "[ミリ秒]");
   }
}
出力結果
...
99991
素数の数:9592
除算を行った回数:455189150
実行時間 : 2063[ミリ秒]

例2:エラトステネスの篩(ふるい)

エラトステネスの篩(Sieve of Eratosthenes)とは
 => ある数までの素数を探す場合、その数の平方根より小さい素数の倍数を消せば、残った数が素数である

 例:100までの素数を探す
  => 100の平方根(√100)は、10である
  => 10までの素数は、「2、3、5、7」である
  => 2の倍数(2,4,...,100)、3の倍数(3,6,...,99)、5の倍数(5,10,...,100)、7の倍数(7,14,...,98)を消していく
  => その残りが、100までの素数(2、3、5、7、11、13、・・・)である

 消していく様子を、ふるいに掛けている感じ。
手順
 [1] ある数までの全整数データを用意する(例:10以下の整数データを用意する)
 [2] 平方根以下の素数の倍数を取り除く(例:10の平方根(√10≒3.16)までの倍数を取り除く)
 [3] 最後まで残った数を素数として出力する(例:残った数を出力する)
SampleInitialNumber2.java
public class SampleInitialNumber2 {
   public static void main(String[] args) {
      long start = System.currentTimeMillis();
      // 0 - 100000までの素数を出力する
      int num = 100000;
      // 素数の数をカウント
      int initialCount = 0;
      boolean[] areInitialNumbers = new boolean[num];
      
      // 初期化(初めは素数であるとする)
      for (int i = 2; i < num; i++) {
         areInitialNumbers[i] = true;
      }

      // ふるいにかける
      for (int i = 2; i < num; i++) {
         if (!areInitialNumbers[i]) {
            continue;
         }
         for (int j = 2 * i; j < num; j += i) {
            // 素数じゃない
            areInitialNumbers[j] = false;
         }
     }
      
      // 出力
      for (int i = 2; i < num; i++) {
         if (areInitialNumbers[i]) {
            initialCount++;
            System.out.println(i);
         }
      }
      
      long stop = System.currentTimeMillis();
      System.out.println("素数の数:" + initialCount);
      System.out.println("実行時間 : " + (stop - start) + "[ミリ秒]");
   }
}
出力結果
...
99991
素数の数:9592
実行時間 : 256[ミリ秒]