問題
- N (1000以下のN)までの素数を求めよ。
エラトステネスのふるいを、プログラムにしよう。
下のプログラムテンプレートを使い、②にあたる部分を作成せよ。(関数にしてもよい)
実行例
n : 50 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47
解答例
[プログラム]
#include <stdio.h> #include <math.h> #define N 50 // プログラム中のNという文字を、50におきかえ int main (void) { int p[N+1]; int i, j, max; /* 外側、内側、√N */ max = sqrt((float)N); /* Nは整数。実数型へキャスト(型変換)して平方根。 さらに、intに型変換されてmaxに代入。小数点以下が切り捨てになる。 */ /* ① p[2] - p[N]を1に初期化 */ for (i = 2; i <= N; i++) p[i]=1; /* ② エラトステネスのふるい。各自、確認 */ /* もし素数ではないなら、素数番目の配列pは、0にしよう */ /* ② エラトステネスのふるい。ルートN以下の素数について、直接、素数の倍数を篩に。 i以上の数に倍数かどうかを割り算して判定すると、先週の解法2になってしまう。*/ for (i = 2 ; i <= max; i++) /* 条件部 maxは切り捨てになっているから、 =がいる。なお、条件部にi*i < Nという書き方もうまい */ if(p[i] == 1) /* if(p[i]) とするのもうまい。 for(j = 2; i*j <= N ; j++) p[i*j] = 0; /* if [i*j] == 1 とチェックしていない。重複して0を代入 */ /* 内側のループの別の例:iを繰り返し足しこんで倍数を得ていく方法。 j = 3*iなど、初期値の工夫もよい for(j = i; j <= N ; j+=i) p[j] = 0; */ /* こちらは誤り すべての数に倍数かどうかを余りで判定している for(j = i; j <= N ; j++) { if(j%i == 0) p[j] = 0; */ /* ③ 値が1のものは素数。 */ printf("n : %d \n", N); for(i = 2; i <= N ; i++) if(p[i]==1) printf("%3d", i); printf("\n"); return 0; }
コメント