/* 偏差計算、配列、並べ替え 1-7.c */
#include <stdio.h>
#include <math.h> // 今回は、このinclude文も書いておく。
/* math(mathematics=数学).hは、数学の関数を色々定義してあるheader file。
平方根を求めるのに必要。*/
main()
{
/* 平均値や最大・最小値を求める場合には入力値に当てる変数は一つでも良い。しかし、個々の
値を呼び出して何らかの処理をしたい場合には、変数がdataの数だけ必要になる。その場合、個別
に異なった変数名を付けると手に負えなくなるので、同じ変数名で幾つものdataを扱えるように
する。それが配列である。
*/
int i,j,a,n;
int d[1000]; // [ ]の形に注意。幾つdataがあるか分からないので多めに宣言。
float sum,s2;
/* ここで int d[1000]としたのが、整数型の配列宣言である。これは、d[0],d[1],d[2],,,,,,
という様に、[ ]中の数(=添え字)の違いで異なる変数を表す。d[10]と宣言した場合、変数d[]は
10個確保される。ただし一番初めが[0]なので、最後は[9]になる。10番目の積もりでd[10]に値を
入れるとエラーになるので注意。うっかり… が結構ある。
先ず、配列を使わずに平均と標準偏差を求める。
*/
printf("入力dataの平均値と標準偏差を求める。[終了=999]\n");
sum=0;s2=0; // 初期化。
for (i=0;i<1000;i++) { // data数が幾つか分からないので、回る数を多めに取っておく。
printf("No.%2d:",i+1); // %2dと書くと 2桁右詰め表示。
scanf("%d",&a); // &を忘れぬ事。
if (a==999) break; // 入力値 aが999だったら、loopを抜ける。
sum+=a; // 総和
s2+=a*a; // 平方和
}
/* 標準偏差を求めるには、先ず偏差平方和(平方和から総和の平方をdata数で割ったものを引く)
を計算。それを更に(data数-1)で割って分散を求め、その平方根を取る。data数は iなので、次の
様に書ける。
*/
s2=s2-sum*sum/i; s2=s2/(i-1); s2=sqrt(s2);
/* 整数宣言された数値同士の計算結果は整数になってしまうので、それを避ける為に予め sumも
s2も float宣言した。sqrtが平方根を求める関数。文末には必ず;を付ける。
*/
printf("(n=%d) sum=%.f mean=%.2f sd=%.2f\n\n",i,sum,sum/i,s2);
/* 配列を使わなくても計算は出来るが、後で入力値を知りたい時にはどうしようも無い。
今度は配列宣言したd[]にdataを読み込んで同じ計算をする。*/
printf("入力dataの平均値と標準偏差を求める [配列変数を使う。終了=999]\n");
sum=0;s2=0; // 初期化
for (i=0;i<1000;i++) {
printf("No.%2d:",i+1);
scanf("%d",&d[i]);
if (d[i]==999) break;
sum+=d[i];
s2+=d[i]*d[i];
}
s2=s2-sum*sum/i; s2=s2/(i-1); s2=sqrt(s2); // 偏差計算
printf("(n=%d) sum=%.f mean=%.2f sd=%.2f\n\n",i,sum,sum/i,s2);
printf("\n入力dataの 3番目を表示\nNo.3=%d\n",d[2]);
/* 配列変数は[0]から始まるので、一つ前の添え字にする。*/
printf("この様に、配列を使えば後でdataを呼び出せる。\n\n");
printf(" ? 番目の値を表示(data No.入力):");
scanf("%d",&a); if (a<=i) printf("No.%d=%d\n",a,d[a-1]);
printf("もう一度やってみる\n ? 番目の値を表示(data No.入力):");
scanf("%d",&a); if (a<=i) printf("No.%d=%d\n",a,d[a-1]);
/* if文を使ったのは、data数を超える数が添え字に入るとエラーになるから。data数が iで
最後のdataはd[i-1]、d[i]は 999になっている。*/
/* dataの並べ替えをして見る */
n=i; // iを使ってloopを回すので、data数を nに納めておく。
for (i=0;i<n-1;i++) {
for (j=i+1;j<n;j++) {
if (d[i]>=d[j]) {a=d[i]; d[i]=d[j]; d[j]=a;}
}
}
/* これが良く使われる並べ替えのアルゴリズムである。iを 1から(data数-1)まで回し、i番目
の値とそれ以降の全ての値を比較。後の値が小さければ交換するので、先頭から小さい順に並ぶ
事になる。Basic言語では、この種の交換にswap(交換)命令を使うが、Cにはswap命令が無いので
上の様にしている。値を預ける変数を用意しておいて、順繰りに値をずらして代入していくと、
交換が成立する。i loopの中で j を回すことは良く行われる(nesting, 入籠)。iとjの関係に目
配り。 forも whileも ifも、( )後の一文のみを実行するので、複数の命令を実行させる場合に
は{ }で囲むのを忘れない事。条件文を( )中に書くことも[つい()抜きで書くことが…]。
*/
printf("\n配列を使わないと出来ない処理の例\ndataを小さい順に並べ替えて表示\n\n");
for (i=0;i<n;i++) printf("%d, ",d[i]);
printf("\nEnd\n");
return 0;
}