SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

Fibonacci数の計算で学ぶ、PHPでの多倍長整数の扱いとベンチマーク方法

PEARライブラリ活用 (6)


  • X ポスト
  • このエントリーをはてなブックマークに追加

ベンチマーク (Benchmark)

 先に述べたように、Fibonacci数は非常に速く増大し、intの範囲などは簡単に超えてしまいます。そのため、多倍長整数という仕組みを用いて計算するのが一般的です。そのような状況では、単純な計算でも非常に時間がかかる恐れが出てきます。

 例えば、整数の加算は、その対象がintの範囲にあるうちは、計算時間に変化はありません。100+100と1000+1000にかかる時間は同じだと考えていいでしょう。多倍長の場合にはそういうわけには行きません(加算の場合には、桁数に比例する程度の時間がかかると考えなければなりません)。ここではFibonacci数の計算にかかる時間を計測し、このことを体験してみましょう。

1回だけ計測するBenchmark_Timer

 時間の計測にはPEAR Benchmarkを使います。このパッケージに含まれるBenchmark_Timerを使うと、プログラムの特定の部分の処理時間を簡単に計れます。

timer.php
<?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数の計算部分をstartstopで囲み、計算時間を測定しています(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が便利です。

iteration.php
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
)

 平均値と計測回数がすぐに分かるのは便利なのですが、実データとそれらの平均と数という、性質の違うデータが混在していると後の処理が面倒なので、取り除いておきます。

iteration.php
unset($result['mean']);//結果の修正
unset($result['iterations']);

統計処理

記述統計 (Math_Stats)

 複数の数値データを扱う際に、まず平均を調べるというのはよくあることです。先のBenchmark_Iterateの例でも、平均(mean)はすぐに分かるようになっていました。しかし、平均を出してそれで済むことはまれです。最低でも分散(あるいは標準偏差)は調べなければならないことが多いでしょう。

 そのような記述統計量を求めたいときに便利なのが、Math_Statsです。先ほどのBenchmark_Iterateの結果は、計測結果だけになるように修正してあるので、すぐにMath_Statsで処理することができます。

iteration.php
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で描けます。

iteration.php
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はまだβ版です)。

次のページ
Math_Fibonacciの実装

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
特集記事連載記事一覧

もっと読む

この記事の著者

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

WINGSプロジェクト 矢吹 太朗(ヤブキ タロウ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/2807 2010/01/05 11:15

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング