- ベストアンサー
C言語初心者のための調和平均プログラムの修正方法
- C言語初心者の方が調和平均のプログラムを作成している際にうまくいかない問題が発生した場合の解決方法について解説します。
- 調和平均の計算式とは、n個の入力された数値の逆数の和を1で割った値です。ただし、0が入力された場合は値を返さないようにします。
- プログラムの修正ポイントは以下の通りです。1) 0除算の回避、2) 数字の入力終了条件、3) 計算結果の表示方法です。それぞれの修正方法について詳しく解説します。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
いろいろあるようだが、参考にどうぞ。 #include <stdio.h> #include<math.h> #define M 1000 int main (void) /*引数はなくても*/ { // insert code here... double d[M],e[M]; /*d[M]もこれにした*/ double wa=0,av,bun=0,kika=1,tyowa=0; /*avはaverageを,bunは分散を意味します*/ int i=0,j=0; printf("複数の数字を入力してください\n"); printf("数字入力を終了するときはnull文字を入力してください\n"); /*null文字って?*/ printf("数字以外が入力されたら\n"); printf("それまでの数字の計算結果を表します\n"); /*数字を入力、和を求める*/ while (scanf("%lf",&d[i])!='\0') { /*doubleで入力、scanfの問題は別にしておく*/ wa=wa+d[i]; printf("%f\n",wa); i++; } if (i!=0) { av=wa/i; /*これが先のほうがいいだろう*/ printf("算術平均は%fです\n",av); /*で、avにした*/ for (j=0; j<i; j++) { kika=kika*d[j]; } printf("幾何平均は%fです\n",pow(kika,1./i)); for (j=0; j<i; j++) { if(d[j]==0.) { /*論理演算子ね*/ printf("調和平均は出せません\n"); return 0; /*ここで帰ったほうがいい*/ } else { e[j]=1./d[j]; /*e[j]に変える意味はあまりないようだが*/ } } for (j=0; j<i; j++) { /*この辺無駄があるようだがそのままにした*/ tyowa=tyowa+e[j]; } tyowa=i/tyowa; /*これじゃないと調和平均にならないのじゃないかな*/ printf("調和平均は%fです\n",tyowa); /*tyowaを表示*/ for (j=0; j<i; j++) { bun=bun+(d[j]-av)*(d[j]-av); } printf("分散の値は%fです\n",bun/(i-1)); /*不偏分散ならi-1、入力データを母集団とするならi*/ } //else { // printf("数字を入力してください\n"); /*これはいらないだろう*/ //}
その他の回答 (3)
- kmee
- ベストアンサー率55% (1857/3366)
すでに指摘がありますが > if (d[j]=0) { これは、C言語では d[j]=0 の代入を実行→式全体は値は代入した値と等しい(==0)→値が0なので真偽値は「偽」→ifの条件は(常に)不成立 となります。 比較の==と代入の=を間違えるのは、よくある間違いの一つです。0 == d[j]のように定数を左辺に持ってくることである程度は防げますが、根本対策はありません。気をつけましょう。 あとは。 > float d[M]; と宣言していますが、他の計算をdouble使ってますし、精度的にも速度的にも、現在よくある 実行環境ではfloatを使う意味はほとんどありません。 doubleを使った方がよいでしょう。 > while (scanf("%f",&d[i])!='\0') { scanfの%fを%lfにすれば、対象がdoubleになります。 あと > printf("数字入力を終了するときはnull文字を入力してください\n"); とも絡むのですが。 scanfの戻り値をマニュアルで確認してください。 「入力できた値の数(全部失敗で0)/入力がEndOfFileになっていたらEOF」 となっているはずです。入力した文字や文字列を返すようにはなっていません。'\0'と比較しても、それはnull文字が入力されたことの判定にはなっていません。 '\0'は数値の0と同じなので、今回はたまたま、数字以外の文字を入力すればscanfが0を返してループから抜けますが、EndofFile(Unix 系ならCtrl+D,WindowsだったらCtrl+Z後リターン)を入力すると無限ループになります。 (もっとも、その前にd[M]の範囲外となりエラーで止ると思いますが) そもそもnull文字なんて入力できますか? > else e[j]=1/d[j]; 現行では、 (int)1 / (float)d[j] →暗黙の型変換でfloatで計算→暗黙の型変換でdoubleにしてe[j]に代入 となると思います。計算精度に効いてくるので、上記の通り、d[M]はdoubleで宣言しておきましょう。
- sekibunx
- ベストアンサー率61% (8/13)
#1です. 回答の補足です. if (d[j]=0) { このようにifの条件式で代入してしまうと, 0を代入した場合は常にfalse,0以外の場合は常にfalseになります. 今回は0を代入してますので,trueとなり続行しますが, d[j]が0となるのでe[j]はInfiniteになります. あとprintf("調和平均は%fです\n",e[1]);としていますが,これは1/d1を表示しているだけですね. tyouwa = (1/d1+...1/dn)なので,最終的な調和平均はn/tyouwaとなるのではないでしょうか.
- sekibunx
- ベストアンサー率61% (8/13)
計算式はあまり詳しく見てませんが... if (d[j]=0) { printf("調和平均は出せません\n"); } if(d[j]==0) の誤りですね.