• ベストアンサー

C言語<素数を求めるプログラム>

#include<stdio.h> int j; int prime(int n) { int i; if(n < 2) return 0; if(n == 2) return 1; if(n%2 == 0) return 0; for(i = 3; i*i<= n; i += 2){ if(n%i == 0) return 0; } return 1; } int main(void) { int n; for(n=1; n <= 1000; n++) { if(prime(n)){ printf("%d\n",n); j++; } } printf("素数の個数は全部で %d 件見つかりました。\n",j); return 0; } このプログラムは1から1000までの素数のみを表示させるプログラムでありますが、このアルゴリズムが全くわかりません。 int prime(int n)の中身のアルゴリズムがどういう仕組みになっているのかお分かりになりますでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
  • morigann
  • ベストアンサー率17% (57/329)
回答No.2

「int prime(int n)」内についてですが、 if(n < 2) return 0;  →2未満の数字は素数としない、つまり「1」の時は素数ではないと判断したい処理ですね if(n == 2) return 1;  →2の時は無条件に素数と判断する為です if(n%2 == 0) return 0;  →nを2で割った時のあまりが0だったら素数ではない、つまり(2より大きい)偶数の時は絶対素数ではないので偶数をはぶく為の処理ですね for(i = 3; i*i<= n; i += 2){ if(n%i == 0) return 0; }  →割る数(i)を3から5、7、9・・・のように増やしていって、nを割ったときのあまりが0かどうか判断しています。   例:n=9場合、i=3の時に9/3であまりが0になるので、9は3で割り切れるから9は素数じゃない!   の処理をしています。 return 1;  →で、最後のreturnですが、これは説明不要でしょか?   ここに来るまで素数じゃないと判断されたらreturn 0で途中で処理を抜けています。   つまりここまで来たら素数なのでreturn 1を返します。 で、よろしいでしょうか?

gigab3476
質問者

お礼

大変わかりやすい回答有難うございました。 こちらと致しましても、なんかわかりそうな気がしました。 return 1;が素数の処理で、return 0;が素数でない処理なのですね。

その他の回答 (3)

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.4

★アドバイス ・morigann さんへ。 >初期値不定のまま、いきなり「j++」してしまうと計算結果が無茶苦茶になる可能性あります。  ↑  j はグローバル変数なので初期化されますよ。つまり 0 です。 ・gigab3476 さんへ。  なぜ、j 変数はグローバル変数にしているのですか?  特に他の関数などで参照しないのであれば j は main() 関数内で宣言(初期化)しておきましょう。  int main( void )  {   int j = 0; ←初期化   int n;    :   printf( "素数の個数は全部で %d 件見つかりました。\n", j );   return 0;  } ・以上。

gigab3476
質問者

お礼

なるほど。そうなんですか。 丁寧なご指摘有難うございます。

  • morigann
  • ベストアンサー率17% (57/329)
回答No.3

余談ですが#2の追記です。 jが初期化されてないので、int main(void)のFor文に入る前に0で初期化しておくべきです。 初期値不定のまま、いきなり「j++」してしまうと計算結果が無茶苦茶になる可能性あります。

  • php504
  • ベストアンサー率42% (926/2160)
回答No.1

試し割りの素数判定法ですね nが素数かどうかを判定するのに3から√nまでの整数で順番に試しに割ってみて割り切れたら素数ではないという方法です。

関連するQ&A

  • 【C→JAVA】素数の組の数を求めるプログラム

    以下はC言語のプログラムです。 標準入力に正の偶数値 n(2≦n≦10,000) を入力すると足して n になる素数の組の数を求め、 標準出力に出力するプログラムなのですが、 これをJAVA用のプログラムに置き換えるとすると どのようなプログラムになるのでしょうか? よろしくお願いいたします。 #include <stdio.h> #include <math.h> //Compiler version gcc 6.3.0 #define N 10000 int primes[N + 1] = {0}; void sieve(int); int main() { int n,count = 0; sieve(N); scanf("%d",&n); for (int i = 1;i <= n / 2 + 1;i++) { for (int j = i + 1;j < n;j++) { if (primes[i] && primes[j] && i + j == n) { count++; } } } printf("%d\n",count); return 0; } void sieve(int n) { int limit = (int)sqrt(n) + 1; for (int i = 2;i <= n;i++) { primes[i] = 1; } for (int i = 2;i < limit;i++) { if (primes[i]) { for (int j = 2; i * j <= n;j++) { primes[i * j] = 0; } } } }

  • プログラムについて(C言語)

    #include<stdio.h> int main() { int i,n,total; for(;;){ /* 無限ループ*/ printf("整数n?"); /* nの値の表示 */ scanf("%d",&n); /* ifとbreakを使った終了判定 */ if(n<0)break; total=1; for(i=1;i<=n;i++){ printf("i=%d ",i); total*=i; /* total←total*i(階乗の計算) */ } printf("total=%d\n",total); /* totalの値(結果)の表示 */ } printf("Thanks\n"); /* 終了メッセージの表示 */ return(0); } これは階乗を求めるプログラムなのですが、i++ではなくi--をつかって求める場合 どのように変更すればよいでしょうか? for(i=1;i<=n;i++){ あたりをいろいろ弄ってみたのですが、求めてる結果は得られませんでした

  • C言語で分からないところがあるのですが……

    C言語で分からないところがあるのですが…… すみません。C言語の課題で分からないところがあり、質問しに来ました。 ユーザから数を受けて、そこまでのフィボナッチ数列を表示させるというプログラムです。 下のソースコード(でいいんですよね?)は正しいやつです。 for文を使って、繰り返しの作業を行うことに成功しましたが、doとwhileに書き換える作業がうまくできません。 どなたか助けてください。 #include<stdio.h> fib(int n) { if(n == 1)return(1); else{ if(n == 2) return (1); else return fib(n-1) + fib(n-2); } } main() { int n, i ; printf("INPUT the number. : "); scanf("%d",&n); for(i=1; i<=n; i++){ printf("F%d = %d\n",i, fib(i)); } }

  • C言語のプログラムでおかしな動作をするのですが教えて頂けないでしょうか?

    VisualStudio2008使用しています。 問題は、サイコロを200回振ってその出た目の数の個数分*を表示するプログラムです。 サイコロの目はランダムで出しています。 次のプログラムは正常に動作するものです。 /* #include <stdio.h> #include<stdlib.h> #include<time.h> #define N 200 int DICE(int min,int max); int main() { int n,i,j; int y[7]={0}; srand((unsigned int)time(NULL)); for(i=0;i<N;i++){ n=DICE(1,6); y[n]++; } for(i=1;i<7;i++){ printf(" %2d: ",i); for(j=0;j<y[i];j++){ printf("*"); } printf("\n"); } return 0; } int DICE(int min,int max) { return min+(int)(rand()*(max-min+1.0)/(1.0+RAND_MAX)); } */ 次のプログラムが問題で、授業で先生が配列にはstaticをおまじないとしてつけないと暴走すると言われたので、つけて見ると明らかに間違ってると思われるプログラムで動作するのですが原因を教えて頂けないでしょうか? 以下問題のプログラム! 配列の前にstaticをつけたら、添え字をいくつにしても正常に動作します。普通は添え自分しか領域って確保されないですよね??? /* #include <stdio.h> #include<stdlib.h> #include<time.h> #define N 200 int DICE(int min,int max); int main() { int n,i,j; //以下が問題の配列宣言 static int y[2]={0}; srand((unsigned int)time(NULL)); for(i=0;i<N;i++){ n=DICE(1,6); y[n]++; } for(i=1;i<7;i++){ printf(" %2d: ",i); for(j=0;j<y[i];j++){ printf("*"); } printf("\n"); } return 0; } int DICE(int min,int max) { return min+(int)(rand()*(max-min+1.0)/(1.0+RAND_MAX)); } 質問の意味が正確に伝わらなかった場合は補足しますので、ご回答よろしくお願いします。

  • C言語でのプログラム

    全対最短経路(フロイドのアルゴリズム)のプログラムを作成したんですが、以下のようなメッセージが出てしまい、どこが悪いのかさっぱりわかりません。どなたかご教授願えないでしょうか? <プログラム> #include<stdio.h> #define NC 999 /* It should be large enough. */ #define N 5 void floyd(int, int [][], int [][], int [][]); int W[N][N] = { { 0, 1, NC, 1, 5 }, { 9, 0, 3, 2, NC }, { NC, NC, 0, 4, NC }, { NC, NC, 2, 0, 3 }, { 3, NC, NC, NC, 0 }, }; int P[N][N]; int D[N][N]; main() { floyd(N, W, D, P); } void floyd(int n, int W[][], int D[][], int P[][]) { int i, j, k; for(i=0;i<n;i++){ for(j=0;j<n;j++){ P[i][j] = 0; } } for(i=0;i<n;i++){ for(j=0;j<n;j++){ D[i][j] = W[i][j]; } } for(k=0;k<n;k++){ for(i=0;i<n;j++){ for(j=0;j<n;j++){ if(D[i][k]+D[k][j]<D[i][j]){ P[i][j] = k; D[i][j] = D[i][k] + D[k][j]; } } } } printf("?nall pairs of the shortest pathes:?n"); for(i=0;i<n;i++){ for(j=0;j<n;j++){ printf("%3d ", D[i][j]); } printf("?n"); } printf("?n"); } <エラーメッセージ> In function `floyd': :30: error: invalid use of array with unspecified bounds :36: error: invalid use of array with unspecified bounds :43: error: invalid use of array with unspecified bounds :44: error: invalid use of array with unspecified bounds :45: error: invalid use of array with unspecified bounds :54: error: invalid use of array with unspecified bounds

  • c言語 

    答えを0にするこまち算のプログラムを組んでみたのですが、ここからどうしても進まなくなってしまいました。 自分ではいけるかなと思ったのですが、9-8-7+65-4321=9など答えがありえない数になってしまいます。 どこがいけないか教えてください。むしろ最初から組み直した方がよいのでしょうか… #include <stdio.h> int cul(); int num[9] ={9,8,7,6,5,4,3,2,1}; int total;/**/ int kigou[8]={0,0,0,0,0,0,0,0}; int main(){ for(kigou[0]=0;kigou[0]<3;kigou[0]++){ for(kigou[1]=0;kigou[1]<3;kigou[1]++){ for(kigou[2]=0;kigou[2]<3;kigou[2]++){ for(kigou[3]=0;kigou[3]<3;kigou[3]++){ for(kigou[4]=0;kigou[4]<3;kigou[4]++){ for(kigou[5]=0;kigou[5]<3;kigou[5]++){ for(kigou[6]=0;kigou[6]<3;kigou[6]++){ for(kigou[7]=0;kigou[7]<3;kigou[7]++){ keisan(); } } } } } } } } return 0; } int keisan(){ int n =0; int flag = 0; int t = 0; int i = 0; total = num[0]; /* for (n=0;n<9;n++) printf("kigou[%d] == %d",n,kigou[n]);確かめ*/ for(;n<8;n++){ if(kigou[n] == 0 && n == 0){ total = total * 10 + num[n+1]; for(flag=1;kigou[n+flag]==0 && (n+flag)<9 ;flag++){ total = total * 10 + num[n+flag+1]; } n = n + flag; } flag=0; if(kigou[n]!= 0){ for(flag=1;kigou[n+flag]==0 && (n+flag)<9 ;flag++){ t = num[n+1] * 10 + num[n+flag+1]; } n = n+ flag; total = total + t; } } /*0になる計算式の表示*/ kigou[8]=2;/*表示しないために空白を入れる*/ if(total==0){ for(i=0;i<9;i++){ printf("%d",num[i]); if(kigou[i]==0) printf("+"); if(kigou[i]==1) printf("-"); if(kigou[i]==2) printf(""); } printf("=%d\n",total); } return 0; }

  • c言語 パスカルの三角形

    c言語でパスカルの三角形を出力するプログラムを作りたいのですが、上手くいきません。 何を直せばいいのか教えてください。 #include <stdio.h> #define N 10 int main(void){ int i, j = 1, x, y; int d[N][N]; /* 三角形を作成 */ for (i = 1 ; i < N ; i++){ d[i][0] = 1; while (j <= i - 1){ d[i][j] = d[i-1][j-1] + d[i-1][j]; j ++; } } /* 三角形の表示 */ for (y = 0; y < N; y++) { for (x = 0; x < N-y; x++) printf(" "); for (x = 0; x < y; x++) printf("%3d ", d[x][y]); printf("\n"); } return 0; } 実行結果 -2147417616 2665208 1629976532 1627572249 1629101723 1 1629982744 2665256 2665548 3407923 1629345053 1627571017 0 3538997 1629739051 10 1629345053 2665368 3670071 2665384 1629739040 1627927140 2665244 1628040295 57 1628810863 1629476960 1628602749 2665560 2665304 1629345053 0 1629739040 1629740576 1628992224 2 4411498 1628040588 -2147417600 0 1629476960 1629740664 1629739040 1 267574 0

  • C言語のソートプログラム

    学校でプログラミングの課題が出たので自分のパソコンに Microsoft Visual C++ 2010 Express をインストールして作ってみました。 それが以下のプログラムです。 これは任意の値nを入力してa[n]までの配列をつくり それを降順に並び替えるものです。 #include <stdio.h> #define N 10000 int main(){ int a[N],i,j,max,min,n,temp; n=0; printf("n="); scanf("%d",&n); if(N<n){ return 0; } else if(n<=0){ return 0; } else if(n<=N){ for(i=0;i<n;i++){ printf("a[%d]",i); scanf("%d",&a[i]); } max=min=a[0]; for(i=1;i<n;i++){ if(max<a[i]){ max=a[i]; } else if(min>a[i]){ min=a[i]; } } printf("a[i]のソート結果\n"); for(i=0;i<n;i++);{ for(j=i+1;j<n;j++){ if(a[i]<a[j]){ temp=a[i]; a[i]=a[j]; a[j]=temp; } } } for(i=0;i<n;i++){ printf("a[%2d]=%d\n",i,a[i]); } printf("Max=%d\n",max); printf("Min=%d\n",min); } } これを実行すると 最初に入力した配列の順番のまま表示されてしまいます。 例えば n=4 a[0]7 a[1]4 a[2]6 a[3]1 a[i]のソート結果 a[0]7 a[1]4 a[2]6 a[3]1 のようにです。 しかしプログラミング上では for(i=0;i<n;i++);{ for(j=i+1;j<n;j++){ if(a[i]<a[j]       temp=a[i];       a[i]=a[j];            a[j]=temp;        }        }        } のようにiとjを比較して a[0]がa[1]より大きければa[0]とa[1]を交換する。 あとはa[0]とa[2], a[0]とa[3]...a[3]とa[4]まで for文の続く限り繰り返すように書いたはずです。 まだ勉強し始めた私にはどこが間違っているのか分からないので 分かる方はご指摘をお願いします。

  • C言語の問題を教えてください。初心者です。

    1000以下の整数を入力して、それ以下の素数を出力するプログラムをつくっています。 一応自分でやってみたのですが、どうもうまくできません。自分ではどこが間違っているのかさっぱりなので間違い箇所を指摘し、どうすれば良いのかを教えていただきたいです。ほかに効率的なやりかたがあったらあわせてお願いします。 初心者なので易しく説明していただけるとありがたいです。 <自分でやってみた> #include <stdio.h> int main(){ int i,j,N; int a[1000]; for (i=2; i<=1000; i++) { a[i]=1; } for (i=2; i<=1000; i++) { for (j=i++; j<=1000; j++) { if (a[j]=1 && j%i==0) { a[j]=0; } } } printf("2以上1000以下の整数を入力してください\n"); scanf("%d",&N); printf("%d以下の素数は\n",N); for (i=2; i<=N; i++) { if (a[i]=1) { printf("%d\n",i); } } } よろしくお願いしますm(_ _)m

  • C言語でこのプログラムを完成させるには

    C言語でこのプログラムを完成させるには C言語初心者です。 1~6の乱数を100回発生させて、それぞれの出現回数をカウントし、ヒストグラムとして表示するプログラムを作成したいのですが上手くいきません。 #include <stdio.h> #include <time.h> #include <stdlib.h> int rnd(int m, int n) { return (int)(n-m+1)*(rand()/(RAND_MAX+0.1))+m; } int main(void) { int i, j, r; int hist[7]; for (i=1; i<7; i++) hist[i]=0; srand((unsigned)time(NULL)); for (i=0; i<100; i++) { r=6; while (6-- > 0) putchar('*'); putchar('\n'); } for (i=1; i<7; i++) { printf("%2d:", i); for (j=0; j<hist[i]; j++) printf("*"); printf("\n"); } return 0; } 何がいけないのでしょうか? よろしくお願いします。

専門家に質問してみよう