配列の例題 平均値と標準偏差  1999.03.19(初版)

 配列は一連のデータを一旦記憶しておいて利用する必要があるときに使われま 
す。例としてデータの平均値と標準偏差を求める場合を考えます。 

 平均値を求めるだけの場合、配列は必ずしも必要ありません。次のプログラムを 
見てください。 
// sample01.cpp
// 平均値
#include <iostream.h>
#include <iomanip.h>

int main()
{
    cout << "10個の整数データを入力してください:" << endl;

    int sum = 0; // データの合計(0で初期化)
    int data;    // 入力データ
    for(int i = 0; i< 10; i++){
        cout << setw(3) << i+1 << ": ";
        cin >> data;
        sum += data;
    }
    cout << "合計値: " << sum << endl
         << "平均値: " << sum / 10.0 << endl;

    return 0;
}
ソースファイル sample01.cpp
[実行結果]
10個の整数データを入力してください:     
  1: 12 
  2: 23 
  3: 67 
  4: 31 
  5: 55 
  6: 9 
  7: 42 
  8: 81 
  9: 63 
 10: 70 
合計値: 453 
平均値: 45.3
10個のデータをキーボードから読み取り、それらの合計と平均値を求めます。 入力されたデータdataを繰り返しsumに加算して行きます。dataの値は入力され る度に更新されます。この場合データを記憶する変数は1つで間に合います。  次に、平均値と同時に標準偏差も求めることにします。
平均値と標準偏差 標準編差はデータが平均値からどれくらい離れて散らばっているかを測る尺度です から、平均値と個々のデータの値が必要です。
// sample02.cpp
// 平均値と標準偏差
#include <iostream.h>
#include <iomanip.h>
#include <math.h>

int main()
{
    cout << "10個の整数データを入力してください:" << endl;

    const int n = 10;  // データ数
    int data[n];// 入力データを納める配列
    double sum = 0.0;

    // データを入力して平均値を求める
    int i;
    for(i = 0; i< n; i++){
        cout << setw(3) << i+1 << ": ";
        cin >> data[i];
        sum += data[i];
    }
    double ave = sum /n; // 平均値
    cout << "  合計値: " << sum << endl
         << "  平均値: " << ave << endl;

    // 標準偏差を求める
    sum = 0.0;
    for(i = 0; i < n; i++)
        sum += ( data[i] - ave ) * ( data[i] - ave );

    double stdv = sqrt( sum /n );
    cout << "標準偏差:" << stdv << endl;

    return 0;
}
ソースファイル sample02.cpp
このプログラムのように標準偏差を求めるために、入力時のデータを記憶してお く必要があります。2つのforループが示すようにデータを2回走査することに なります。この場合1回目の走査(データ入力)で配列にデータを格納しておき ます。2回目の走査で標準偏差を計算します。  実は、標準偏差を求めるには配列を使わない方法もあります。標準偏差の式は 次のように変形できます。
この式では、総和の中に平均値がありません。平均を求めるためのデータの和と、 データの2乗和を求めるだけです。つまり平均値と同時に標準偏差を求めることが できます。
// sample03.cpp
// 平均値と標準偏差(配列を使わないバージョン)
#include <iostream.h>
#include <iomanip.h>
#include <math.h>

int main()
{
    cout << "10個の整数データを入力してください:" << endl;

    const int n = 10;  // データ数
    int data;          // 入力データを納める変数
    double sum1 = 0.0; // 和
    double sum2 = 0.0; // 2乗和

    // データを入力して平均値と標準偏差を求める
    int i;
    for(i = 0; i< n; i++){
        cout << setw(3) << i+1 << ": ";
        cin >> data;
        sum1 += data;
        sum2 += data * data;
    }
    double ave  = sum1 / n; // 平均値
    double stdv = sqrt(sum2 / n - ave * ave);// 標準偏差
    cout << "  合計値: " << sum1 << endl
         << "  平均値: " << ave  << endl
         << "標準偏差: " << stdv << endl;

    return 0;
}
ソースファイル sample03.cpp
こちらのバージョンでは配列を使わないので余分なメモリが節約でき、走査は1回です みますから効率的といえます。  しかし欠点もあります。上の式を見ると平方根の中で、2乗和と平均値の2乗との引 き算になっています。もしこの2つの値が非常に大きくてしかもその差が小さい場合は、 桁落ちによる計算誤差を生じる可能性があります(この意味分かりますか)。 【演習問題】桁落ちが生じることで、起こりうる最悪の事態は何か。 【演習問題】2番目のバージョンで、桁落ちが生じないようなプログラムを考えなさい。

| 目次 | 戻る |

Copyright(c) 1999-2001 Yamada,K