情報基礎A 「Cプログラミング」総合演習

このページでは、電力量のデータをCのプログラムで扱うための「支援プログラム(tsa-helper.c)」について、使い方や仕様を説明する。

「支援プログラム」の仕様

データの表現

基本的に、時刻は、対象とする年の元旦午前0時からの経過時間(整数値)で表現する。

電力量はfloat型の実数値で表現。単位は 万kW・時。

CSV形式のデータの読み出し

int n ;
float data[10000] ;
・・・
n = read_csv("CSVファイル名",data) ;

あらかじめ、データを格納するのに十分な大きさのfloat型の配列を用意しておく (上の例では、配列data。1年分で24*365 = 8760 以上のサイズが必要)。 read_csv()関数は、"CSVファイル名"で指定したファイルから電力量の数値を読み出し、 時間ごとの電力量(万kW・時)を、float型の配列に順に格納する。 読み込まれたデータ点の数の総数(時系列の長さ)が、関数の戻り値として返される(上の例では変数nにそれがセットされる)。 すなわち、注目している年の、正月深夜0時から1時までの電力量が data[0]、大晦日23時から24時までの電力量は data[n-1] にセットされる。

ただし、今年分のデータについては(まだ大晦日はずっと先なので)、「ダウンロードした日より前(のある時点)」で、データはおしまいとなっている。 そんな場合でも、(上の例の)変数nには、ただしいデータ件数がセットされるようになっている。 閏年で年間の時間数が平年と異なる場合も同様。

実行後に、読み込みファイル名と、読み込まれたデータ数が、画面に出力される。

経過時間から日付/時刻への換算

print_date_plus_hour(西暦年, 月, 日, 時間数) ;

基点となる年月日の深夜零時から、指定した時間数が経過した後の、「年/月/日 時刻」を画面にプリントする。 行末の改行コードなし。

  print_date_plus_hour(2011,1,1,1234) ;
  printf("\n") ;

上記のプログラム(の部分)を実行すると、画面には

2011/2/21 10:00

と表示される。2011年1月1日午前0時から1234時間後は"2011/2/21 10:00"である。

二つの日付/時刻が何時間離れているかを計算

 int d ;
 ・・・
 d = diff_in_hour(年1, 月1, 日1, 時刻1, 年2, 月2, 日2, 時刻2) ;

二つの時刻:(年2)/(月2)/(日2) (時刻2):00 と (年1)/(月1)/(日1) (時刻1):00 の差を、時間を単位として返す。

  int d ;
  ・・・
  d = diff_in_hour(2012,7,1,0,2012,8,1,0) ;
  printf("%d\n",d) ;

を実行すると、2012/8/1から2012/7/1までの(1ヶ月の)時間数に相当する744がプリントされる。

日付から曜日を求める

バグを修正しました(7/16)

 int dow ;
 ...
 dow = day_of_the_week(西暦年, 月, 日) ;

西暦年/月/日 をそれぞれ整数値として与えると、対応する曜日を整数値として返す。 0が日曜、1が月曜、...、6が土曜。

ARモデルの係数を求める

仕様を変更しました(7/16)

 float data[10000] ;
 float coef[51],sigma ;
 int n,p ;
 ・・・
 n = read_csv("CSVファイル名",data) ;
 ・・・
 p = 次数 ;
 sigma = arcoef(p, n, data, coef) ;

時系列データ(data)を元に、AR(p)モデルの係数を計算し、配列(coef)にセットする。 coef[0]には前ページの解説の$a(0)$が、coef[1]には$a(1)$が、 coef[p-1]には$a(p-1)$が、それぞれ対応し、 coef[p]には定数項$c$がセットされる。 よって、係数を格納する配列(coef)はp+1以上の大きさを確保する必要がある。 また、関数の戻り値として、ランダムな変動分の標準偏差(予測誤差)$\sigma$が変数sigmaにセットされる。

プログラム上、モデルの次数(pの値)として設定できる上限値は999。

ガウス分布に従う乱数を生成する

 float r ;
 ...
 r = dgauss() ;

平均0, 分散1のガウス分布に従う乱数値を返す。 dgauss()を呼び出す度に、異なる(乱数の)数値が、上の例では変数rにセットされる。 dgauss()関数を使った次のコード

  for (i=0; i<5 ; i++) printf("%f ",dgauss());
  printf("\n") ;

を実行すると、例えば、

1.115775 -0.738492 0.720115 0.044360 -0.370444

擬似乱数は、「毎回違う動作をさせる」などの目的で、ゲーム等にも使われている。

のように表示される。このように、コンピュータによって擬似的にランダムな数値が生成することができて、 その分布を調べると、ガウス分布(正規分布)になっている(そうなるようにプログラムされている)。