美文网首页
投针实验计算Π值的可视化

投针实验计算Π值的可视化

作者: zhuangX | 来源:发表于2019-06-16 21:36 被阅读0次

    1.介绍

        18世纪,法国数学家Buffon提出了“投针实验”,即“在平面上画有一组间距为a的平行线,将一根长度为的针l(l≤a)任意掷在这个平面上,求此针与平行线中任一条相交的概率。”,并证明其概率为2l/πa。
        因为它与π有关,所以常用投针实验来估计π值。
        由蒙特卡罗方法(即频率估计概率)可知,掷的次数越多,针与平行线相交的频率越接近概率,此时求出的π值也越来越精确。

    2.思路

       下面我们将通过程序可视化该实验并计算π值,为方便起见,我们取针长l=a/2,此时概率为1/π。
       (1) 平面:Canvas
       (2) 线:Canvas中绘制直线
       (3) 针:Canvas中绘制直线(随机生成针头位置(x,y)和针与平行线夹角α)
       (4) 相交概率:针头和针尾与某一平行线的差值乘积小于零说明针与该平行线相交

    3.结果

        程序很简单,故不多做赘述。
        可视化如下图所示:


    图一 投针实验的可视化

        经验证,实验误差比较大,但还是可以看出在慢慢接近π值。

    试验次数 π值
    10 10
    100 2.9411764705882355
    1000 3.125
    10000 3.189792663476874
    100000 3.1738978639667375

    4.代码

    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="UTF-8">
      <title>needleProblem</title>
    </head>
    <body>
    
      <canvas id="myCanvas"></canvas>
      <br>
      <input id="times" type="text">
      <button id="submit">提交</button>
      
      <script type="text/javascript">
      
        // 初始化
        const myCanvas = document.getElementById("myCanvas");
        myCanvas.width = 500;   // 只能在这里设置,CSS中的设置没有作用
        myCanvas.height = 500;
        const context = myCanvas.getContext("2d");
        const a = 10;
        
        let arr = [];
        // 绘制线
        for (let i = 0; i < myCanvas.height; i += a) {
          context.beginPath();
          context.moveTo(0,i);
          context.lineTo(myCanvas.width,i);
          context.closePath();
          context.stroke();
          arr.push(i);
        }
        
        // 绘制针
        const submit = document.getElementById("submit");
        submit.addEventListener("click", function() {
          const times = document.getElementById("times").value;
          const len = a / 2.0;
          let timesPoint = 0;
          for (let i = 0; i < times; i++) {
            let x1 = Math.random() * myCanvas.width;
            let y1 = Math.random() * myCanvas.height;
            let angle = Math.random() * 2 * Math.PI - Math.PI;
            let x2 = x1 + len * Math.cos(angle);
            let y2 = y1 + len * Math.sin(angle);
            context.beginPath();
            context.moveTo(x1, y1);
            context.lineTo(x2, y2);
            context.closePath();
            context.strokeStyle="red";
            context.stroke();
        
            // 检测针与线的交点
            let length = arr.length;
            for (let j = 0; j < length; j++) {
              if ((y1 - arr[j]) * (y2 - arr[j]) <= 0) {
                timesPoint++;
              }
            }
          }
          alert(times/timesPoint);
        });
      </script>
    </body>
    </html>
    

    相关文章

      网友评论

          本文标题:投针实验计算Π值的可视化

          本文链接:https://www.haomeiwen.com/subject/pelnfctx.html