ベンチマーク (Benchmark)
先に述べたように、Fibonacci数は非常に速く増大し、intの範囲などは簡単に超えてしまいます。そのため、多倍長整数という仕組みを用いて計算するのが一般的です。そのような状況では、単純な計算でも非常に時間がかかる恐れが出てきます。
例えば、整数の加算は、その対象がintの範囲にあるうちは、計算時間に変化はありません。100+100と1000+1000にかかる時間は同じだと考えていいでしょう。多倍長の場合にはそういうわけには行きません(加算の場合には、桁数に比例する程度の時間がかかると考えなければなりません)。ここではFibonacci数の計算にかかる時間を計測し、このことを体験してみましょう。
1回だけ計測するBenchmark_Timer
時間の計測にはPEAR Benchmarkを使います。このパッケージに含まれるBenchmark_Timer
を使うと、プログラムの特定の部分の処理時間を簡単に計れます。
<?php include_once 'Math/Fibonacci.php'; require_once 'Benchmark/Timer.php'; $timer=new Benchmark_Timer;//タイマーオブジェクトの生成 $timer->start();//計測開始 $result=Math_Fibonacci::term(10);//Fibonacci数の計算 $timer->stop();//計測終了 $profile=$timer->getProfiling();//計測結果の取得 print_r($profile); print "\n{$profile[1]['total']} sec.\n";//0.000423 sec.(実行時間) ?>
このコードでは、Fibonacci数の計算部分をstart
とstop
で囲み、計算時間を測定しています(Timerは、途中にチェックポイントを設定するといった複雑な計測もできます。リファレンスマニュアルを参照してください)。
計測結果は次のような形で取得できます。最後のtotalが実行時間になっています。
Array ( [0] => Array ( [name] => Start [time] => 1213607265.79687700 [diff] => - [total] => - ) [1] => Array ( [name] => Stop [time] => 1213607265.79730000 [diff] => 0.000423 [total] => 0.000423 ) )
複数回計測するBenchmark_Iterate
計測を複数回行って、その平均や分散を調べたいという場合には、Benchmark_Iterate
が便利です。
include_once 'Math/Fibonacci.php'; require_once 'Benchmark/Iterate.php'; $iteration=new Benchmark_Iterate;//Iterateオブジェクトを生成 //計測回数と対象、引数を指定 $iteration->run(10, 'Math_Fibonacci::term', 5000); $result=$iteration->get();//計測 print_r($result);//結果の表示
Benchmark_Iterate
オブジェクトのrun
メソッドで、計測回数と対象、引数を指定します。ここでは、f(5000)を10回計測しています。get
メソッドで次のような結果が得られます。
Array ( [1] => 1.562661 [2] => 0.000080 [3] => 0.000064 [4] => 0.000064 [5] => 0.000063 [6] => 0.000064 [7] => 0.000064 [8] => 0.000064 [9] => 0.000064 [10] => 0.000064 [mean] => 0.156325 [iterations] => 10 )
平均値と計測回数がすぐに分かるのは便利なのですが、実データとそれらの平均と数という、性質の違うデータが混在していると後の処理が面倒なので、取り除いておきます。
unset($result['mean']);//結果の修正 unset($result['iterations']);
統計処理
記述統計 (Math_Stats)
複数の数値データを扱う際に、まず平均を調べるというのはよくあることです。先のBenchmark_Iterate
の例でも、平均(mean)はすぐに分かるようになっていました。しかし、平均を出してそれで済むことはまれです。最低でも分散(あるいは標準偏差)は調べなければならないことが多いでしょう。
そのような記述統計量を求めたいときに便利なのが、Math_Stats
です。先ほどのBenchmark_Iterate
の結果は、計測結果だけになるように修正してあるので、すぐにMath_Stats
で処理することができます。
include_once 'Math/Stats.php'; $stat=new Math_Stats();//統計処理用のオブジェクト $stat->setData($result);//データをセットする echo "\nmean: {$stat->mean()}\n";//0.1563252(平均値) echo "stdev: {$stat->stDev()}\n\n";//0.494136031474(標準偏差)
このように、よく使われる記述統計量を簡単に計算することができます。Math_Stats
は、ここで紹介した平均と標準偏差以外にもさまざまな統計量を計算することができます。詳しくは、リファレンスマニュアルを参照してください。
ヒストグラム (Math_Histogram)
Math_Stats
ほど利用頻度は多くありませんが、数値データのヒストグラムを描いてみたいということもよくあります。きれいなグラフを描きたいときはExcelのような表計算ソフトや専用のグラフ描画ツールを使わなければなりませんが、簡単なものならMath_Histogram
で描けます。
require_once 'Math/Histogram.php'; $h = new Math_Histogram();//ヒストグラム描画オブジェクト $h->setData($result);//データをセット $h->calculate();//計算 echo $h->printHistogram();//描画
次のようなテキスト形式のヒストグラムが得られます。
Histogram Number of bins: 10 Plot range: [0.000063, 1.562661] Data range: [0.000063, 1.562661] Original data range: [0.000063, 1.562661] BIN (FREQUENCY) ASCII_BAR (%) 0.156 (9 ) |********* (90.0%) 0.313 (0 ) | (0.0%) 0.469 (0 ) | (0.0%) 0.625 (0 ) | (0.0%) 0.781 (0 ) | (0.0%) 0.938 (0 ) | (0.0%) 1.094 (0 ) | (0.0%) 1.250 (0 ) | (0.0%) 1.406 (0 ) | (0.0%) 1.563 (0 ) | (0.0%)
10回測定しているにも拘わらずFREQUENCYの和が9、割合(%)の合計が100になっていないなどという不具合がありますが、一応、ヒストグラムらしいものは描けるようです(Math_Histogramはまだβ版です)。