[ 0092: ランダムウオーク円周率 ]
[ 西尾三奈さんの出題 ]
青天中学のグラウンドで 棒を投げて
円周率の近似値を求めることをやったそうですが、
暗に三角関数 (sin) が隠れていました。
これは「ビュフォンの針 (Buffon's Needle)」ですね。
(($y - abs(sin($phi))) * ($y + abs(sin($phi))) <= 0)
というのは、棒が何らかの形で中央の線にかかることですね。
すなわち 2 次元の世界です。
これに対して
1 次元の世界で円周率を求める方法をご紹介します。
用意するのは棒ではなくコインです。
コインフリップ(多絵さんのお好きな丁半でもいいです: 笑)で、
表なら右へ 1 進み 裏なら左に 1 進みます。
これをある回数続け最後の位置 (原点からの距離 d) を求めます。
上記のランダムウオークをさらにある回数続け d の平均を求めます。
結果は: average_distance = sqrt(2*n / pi)
になりますが、この式がどうやって出てくるかわかりますか?
グラフは以下のとおりです。
傾き (実は 2 / pi) の逆数をとり 2 倍すると円周率の近似値が求まります。
[ 広世正憲君のコメント ]
違った視点で考えてみましょう。
直線上をランダムな丁半で行ったり来たりするのを、
極座標による円運動に置き換えてみます。
そうすると 1 セット (n 回) が終わったときの位置を横軸に投影して
絶対値をとれば a*abs(cos(θ)) になって円周率が登場します。
当然ゼロに近い値の頻度が高くなります。
さらにこれを N 回おこなって平均をとれば
統計的に円周率が求まるのではないでしょうか?
多絵さん、乱数を使った Perl スクリプトを使って
Excel でヒストグラムを描くなどしてください。
正規分布は登場しないでしょう。
[ 浅見多絵さんのコメント ]
まず三奈ちゃんの説明にしたがって Perl スクリプトを書き
実行してみました。
#!/usr/local/bin/perl
$n = 1000; # 1セットあたりの試行回数。
$N = 1000; # セットの繰り返し回数。
$d1 = 0; # 1セット終了後のスタート点からの距離。
$d2 = 0; # $Nセット終了後の距離合計。
for ($i=1; $i<=$N; $i++) {
$d1 = 0;
for ($j=0; $j<=$n; $j++) {
$d1 += ((rand(1) > 0.5) ? 1 : -1);
}
$d2 += abs($d1); # 合計してゆく。
}
$average = $d2/$N; # 全セットの距離平均。
printf (
"セット数: %4d 距離平均: %.4f piの近似値: %.4f\n",
$N, $average_distance, 2*$N/($average**2);
|
[ 湯会老人のコメント ]
正憲君が考えた円運動を横軸の位置に投影するのは、
原点から離れた最終位置 (1 セットごと) が出現する確率が低くなる
という点では似ていますが、これはランダムウオークですから
マンハッタン酔歩 のように
順列計算 をもとにしたほうがいい気がします。
たとえば 1000 ステップ進んで最終位置が x = 1000 になるのは 1 とおり、
x = 0 になるのは 1000 個 から 500 個 をとった組み合わせの数と同じ、
すなわち 1000!/(500! * 500!) で、 300 桁 ぐらいの数になります。
これはあくまでも平均を求める際の「重みづけ」に反映されますから、
1000 ステップ進んでも最終位置 (原点からの距離 = 絶対値) の平均は
25 ぐらいになるはずです。
これをさらに多数回繰り返すのは安定した値を求めるため。
仮に試行 1000 回 で平均距離が 25 になったとしますと:
円周率の近似値は (1000/(25**2)) * 2 = 3.2
になります。
なお、三奈さんが紹介してくれた式がどこから来るのかは、
これから考えてみます。
[ 浅見多絵さんのコメント ]
先ほどのプログラムの実行結果です。収束は遅いですね。
1セットあたりの試行回数: 5000
距離平均: 56.0300
piの近似値: 3.1854
みたいな感じです。
[ 湯会老人のコメント ]
「逆数から円周率が求まる」という点では
ラマヌジャン (インドが生んだ天才数学者) の計算式を連想させますね。
右辺の級数は何らかの形で順列 (permutation) に関係あるのかも知れません。
登場する定数の意味はさっぱりわかりませんが。
|