おっす、シュモクザメです。c言語アルゴリズム第二弾ですね。やっていきましょう。
前回の記事はこれです。一応今回はこれの続きなので興味あったら見てみてください。
標準偏差とは
標準偏差とは分散の平方根のことです。

いや分散ってなんやねん
分散っていうのは簡単に言うとデータのばらつきを数値化したものです。
例として画像を見てください

赤色のヒストグラムのデータ1も青色のデータ2も平均(ave)が同じことを表してます。
平均は同じでも個々のデータのばらつきは違いますよね。
これを数値化していくことでデータの解析に使えるんですね。
コードの実装
とりあえず標準偏差の計算式を見ていきましょう

個々のデータから平均値を引いたものを二乗したやつN 個集めてN-1で割るって感じですね。
ちなみに今回は分母はN-1で計算しますがNで計算する場合もあります。ご注意ください。
この式を見てパッと思いつくのは
- 平方根があるのでsqrt関数を使う
- シグマの部分はforループを使う
- 平均でもシグマが出てきそうなので別で平均値を求める関数をつくる
くらいですかね。
上2つは標準偏差を返す関数の中の主な要素ですね。
平均値は関数化して関数がややこしくなるのを防ぎます。
一応今回のコードは前回の続きのノリでやるのでデータは配列に格納します。またオブジェクト形式マクロNで人数を設定してます。
平均値を返す関数
まずこれから作りましょう。
普通にforループで前の値を足していって最後に割るだけですね。
そんで関数自体の型はdoubleにしましょう。割るってことは基本的に整数になりませんからね。
double AVE(int v[N]){
int i;
int sum=0;
for(i=0; i<N; i++){
sum += v[i];
}
return (double)sum/N;
}
a = a + bは a += b ですね。
またsumを宣言したときにしっかり初期値0を与えときましょう。
じゃないと値が不定のままforループに突入しますからね。
さらに!返り値のところにはしっかり(double)をつけましょう!
これがないとsum/Nがint型、つまり整数で表示されてしまいます。まあsumとNがint型ですからね。
そこで(double)をつけることで割り算の結果をdoubleで表示するように指示してます。
標準偏差を計算する関数
sqrt関数は値を渡すとその値の平方根が返ってくる関数です。
めっちゃ便利だしよく使うので覚えておきましょう。
注意ですがsqrt関数は標準ライブラリに入ってません!!
使うときはmath.hをインクルードしましょう。
シグマのところはforループを使って前の値にどんどん足していく系のやつですね。平均値のところと同じかんじ。
double S(int v[N]){
int i;
double ave=AVE(v);
double sum=0;
for(i=0; i<N; i++){
sum += (v[i]-ave)*(v[i]-ave);
}
return sqrt(sum/(N-1));
}
ここではforループ用のsumはdoubleで定義しましょう。
aveがdouble型なので、v[i]-aveはdouble型になるからです。
2乗の部分は単純に同じ値をかければよいです。
よく間違う部分としては最後のreturnのsqrtの中身は
sum/N-1ではなく、sum/(N-1)です。N-1で割るからですね。
これで完成ですね。
実際に動かしてみた

大丈夫そうですね。
最後に全体のコードを張っておきます。よかったら参考にしてください。
ではまた次の記事で会いましょう!
#include <stdio.h>
#include <math.h>
#define N 10
double AVE(int v[N]){
int i;
int sum=0;
for(i=0; i<N; i++){
sum += v[i];
}
return (double)sum/N;
}
double S(int v[N]){
int i;
double ave=AVE(v);
double sum=0;
for(i=0; i<N; i++){
sum += (v[i]-ave)*(v[i]-ave);
}
return sqrt(sum/(N-1));
}
int main(void) {
int date[N];
int i;
printf("点数を入力してください (%d人分)\n",N);
for(i=0; i<N; i++){
do{
printf(":");
scanf("%d",&date[i]);
if(date[i]>100 || date[i]<0)
printf("正しい値を入力してください");
}while(date[i]>100 || date[i]<0);
}
printf("ave%f\n",AVE(date));
printf("S%f",S(date));
return 0;
}
コメント