電電高専生日記

高専生活・電子工作・プログラミングの活動記録。とっくに高専生ではない
2014-07-04 (Fri)

モンテカルロ法による円周率算出

最近、下級生が情報工学の課題のモンテカルロ法による円周率算出に悪戦苦闘していました。プログラム習いたての頃にやるには少し難しいかもしれません。

自分も以前その授業でこの課題をやったので、思い出しつつやってみました。それがこれ↓です。


打つ点の数: 
円周率=

算出ボタンを押すと、四角形のキャンバスの中に、任意の数(初期設定では10000)の点がランダムな位置に打たれます。ここで、四角形の内接円があると仮定して、点が円内に打たれたかを判定します。

全て点を打ち終わった後に、打った点の数と円内に打たれた点の数の比を用いて、円周率を算出することができます。

内接円の半径をr、上記の比をx、円周率をpiとおくと、円の面積について以下の等式が成り立ちます。

(四角形×比) (2r)^2*x = r*r*pi (半径×半径×円周率)

piについて解くと、

pi = 4*x

つまり、円周率は4×円内に打たれた点の数/打たれた全ての点の数で求まります。

勿論これで算出した円周率はあくまでも近似値であって、正確ではありません。また、打つ点の数を多くするにしたがい、円周率は正確になっていきます。


ブログ上で動かしたかったので、CanvasとJavaScriptを用いて作りました。以下にソースを示します。

$("#calc_pi").click(function(){
    var cv = document.getElementById("cv");
    var ctx = cv.getContext("2d");
    var w=200, h=200, r=w/2;    //横幅、縦幅、内接円の半径
    var ox=w/2, oy=h/2;           //中心座標
    ctx.clearRect(0,0,w,h);        //キャンバスクリア

    var num_of_dot = parseInt(document.getElementById("num_of_dot").value);    //打つ点の数
    var within_circle = 0;       //円内に打たれた点の数
    var px, py, pr;
    for (var i=0; i<num_of_dot; i++){
        //ランダムな点の座標を決定
        px = Math.floor(Math.random()*w);
        py = Math.floor(Math.random()*h);
        pr = (px-ox)*(px-ox) + (py-oy)*(py-oy);  //中心からの距離の2乗
        if (pr <= r*r){    //円内に打たれた場合
            ctx.fillStyle = "rgba(192,96,96,1)";
            within_circle ++;
        } else {                //円外に打たれた場合
            ctx.fillStyle = "rgba(196,196,196,1)";
        }
        ctx.fillRect(px, py, 1, 1);
    }
    var pi = 4 * within_circle / num_of_dot;
    document.getElementById("pi").value = pi;    //出力
});
[Tag] * JavaScript
Last Modified : 2014-11-16

Comment






非公開コメント