免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2250 | 回复: 0
打印 上一主题 下一主题

PHP实现投镖求PI法,最笨但最有意思 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2016-09-09 13:58 |只看该作者 |倒序浏览
#### 原理见下图:

被称为利用投飞镖的方法求PI



#### 以下总结选自其他网友:

1. Figure2是Figure1的右上角的部分。
2. 向Figure2中投掷飞镖若干次(一个很大的数目),并且每次都仍在不同的点上。
3. 如果投掷的次数非常多,Figure2将被刺得“千疮百孔”。
4. 这时,“投掷在圆里的次数”除以“总投掷次数”,再乘以4,就是PI的值!(具体的推导过程参见原文)


在这个算法中,很重要的一点是:如何做到“随机地向Figure2投掷”,就是说如何做到Figure2上的每个点被投中的概率相等。

有人总结了一下,这个实际上叫做蒙特卡洛算法,我们取一个单位的正方形(1 x 1) 里面做一个内切圆(单位圆),则 单位正方形面积 :内切单位圆面积 = 单位正方形内的飞镖数 : 内切单位圆内的飞镖数 ,通过计算飞镖个数就可以把单位圆面积算出来, 通过面积,在把圆周率计算出来。 注意 ,精度和你投掷的飞镖次数成正比。

#### 我的PHP源码实现:

PHP自带的mt_rand随机函数偏差较大,换成Halton sequence的方法,测试结果见后面

~~~.php

<?php

$count = 0;
// 忍受不了运算时间,可以把$num 改小
// $num 越大,越接近真值
$num = 100000;
for ($i = 0; $i < $num; $i++) {
    // list($x, $y) = array(mt_rand(0, 10000), mt_rand(0, 10000));
    // $x /= 10000; $y /= 10000;
    $x = halton($i, 3);
    $y = halton($i, 7);

    if (($x*$x + $y*$y) < 1) {
        $count++;
    }
}

$pi = 4.0 * $count / $num;
echo $pi."\n";

// 参考Halton sequence


function halton($index, $base) {
    $result = 0;
    $f = 1;
    $i = $index;
    while ($i > 0) {
        $f /= $base;
        $result += $f * ($i % $base);
        $i = floor($i / $base);
    }
    return $result;
}
~~~

源码中halton传入参数是经过几次调整后的,更精确一些,测试PI = 3.14156

mt_rand误差较大,3次结果如下:

        mt_rand-1 => 3.142904
        mt_rand-2 => 3.143196
        mt_rand-3 => 3.139312

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP