查看: 2546|回复: 2

[评测分享] 【ALINX AXU2CGB试用】蒙特卡罗算法计算圆周率 PI

[复制链接]
  • TA的每日心情
    开心
    3 天前
  • 签到天数: 597 天

    连续签到: 1 天

    [LV.9]以坛为家II

    发表于 2021-7-28 21:17:14 | 显示全部楼层 |阅读模式
    分享到:
    本帖最后由 robe.zhang 于 2021-7-29 11:49 编辑

    【ALINX AXU2CGB试用】蒙特卡罗算法计算圆周率 PI

    蒙特卡洛算法理论就是用统计学来计算圆周率PI。

    乍一听是不是觉得很神奇,统计学和圆周率算法能扯上关系,先不说蒙特卡洛算法,也不管能不能扯上关系,先讲个故事:
    1.png
    (图片是借用网上的图片,如有侵权必究,请告知哈)
    如果我在地上画一个正方形,再以正方形一个顶点为圆心边长为半径,画个1/4 圆弧,如上图。

    现在天上下雨了,因为雨点密度是均匀的,所以落入正方形内的雨点的数量和落入圆弧内的雨点的数量之比,就等于正方形面积和1/4圆的面积之比。正方形面积等于RxR,圆弧面积等于PIxRxR/4,PI 诞生了,并且比值中的R可以约掉的,pi 的计算公式如下:

    PI : 4 = 圆弧面积:正方形面积 = 圆弧内雨点数量:正方形内雨点数量。

    OK,现在统计正方形内雨点数量,和圆弧内雨点数量,就可以算出PI 了。

    这个故事就是蒙特卡罗算法计算圆周率的理论,就是这么合情合理又神奇的统计理论计算圆周率 PI。计算出的Pi数值准不准确,就依赖数据量了,毕竟是统计理论得出的数据。

    理论有了,开始操作,统计雨点不现实,那就用随机数产生笛卡尔系坐标点,计算点到圆心的距离,大于边长R,落入上图蓝色区域,小于边长R落入红色区域,统计红色区域点的个数和蓝色区域点的个数,搞定。

    以下是程序跑出的结果:
    2.png

    笔者把 PI数值随雨点数量的变化趋势,画了个图,从图上能看出来统计了1万多组数据, 计算出的PI数值
    一开始剧烈波动,2000 组数据时基本稳定在 3 左右,然后就是一路飘忽不定,收敛很慢,也不准确,满满的统计学特征。
    用物理上专业术语描述,这是个欠阻尼系统,振荡会一直持续下去,振幅会随着时间(雨点数量)增加变小,但永远不会为零
    3.png

    有个日本人用这个算法计算PI,在自己电脑上跑了1年,计算结果据说比较准确。

    此算法也可以在黑金开发板上跑1年,看看数据怎么样

    上源码:源码很短,用 linux bash 语言写的,能在开发板上直接跑
    1. #!/bin/bash

    2. value_x=
    3. value_y=

    4. value_dist=
    5. value_edge=$(( 32767 * 32767 ))

    6. count_cycle=0
    7. count_edge=0
    8. count_total=0

    9. vaule_pi_min=
    10. vaule_pi_max=

    11. for((;;)); do
    12.         value_x=$RANDOM
    13.          value_y=$RANDOM
    14.         value_dist=$(( $value_x * $value_x + $value_y * $value_y ))
    15.         if (( "${value_dist}" < "${value_edge}" )) ;then (( count_cycle++ )); fi
    16.         if (( "${value_dist}" == "${value_edge}" )) ;then (( count_edge++ )); fi
    17.         (( count_total++ ))
    18.         vaule_pi_min=$(echo "scale=50;4 * $count_cycle / $count_total" |bc )
    19.         vaule_pi_max=$(echo "scale=50;4 * ($count_cycle + $count_edge) / $count_total " |bc )
    20.         echo "point($value_x,$value_y),dist($value_dist). count: cycles($count_cycle),edge($count_edge),total($count_total). PI[$vaule_pi_min,$vaule_pi_max]" | tee -a pi.data
    21. done;
    复制代码

    这个代码运行时,会在同目录中产生 pi.data 记录文件,如果第一次跑后,第二次想接着上一次的数据跑,只需要把 pi.data 中最后一次记录中的 cycles,edge,total 数值,赋值给程序中的 count_cycle,count_edge,count_total 三个变量即可。
    可以利用零散时间,累计跑一年,看看结果怎么样




    回复

    使用道具 举报

  • TA的每日心情
    郁闷
    2024-1-31 23:05
  • 签到天数: 144 天

    连续签到: 1 天

    [LV.7]常住居民III

    发表于 2021-7-30 09:04:48 | 显示全部楼层
    本科计算物理的学科实验报告做的就是这个实验。
    和楼主一比,那时候学习的知识与想法好少好少。
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    昨天 21:29
  • 签到天数: 1622 天

    连续签到: 29 天

    [LV.Master]伴坛终老

    发表于 2021-7-30 11:30:06 | 显示全部楼层
    看看我的,9种语言算pi pi.rar (2.35 KB, 下载次数: 4)
    回复 支持 反对

    使用道具 举报

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

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    手机版|小黑屋|与非网

    GMT+8, 2024-11-23 09:47 , Processed in 0.136836 second(s), 21 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.