一、理论篇
1. 数学公式
圆面积公式:π*r*r,其中π为圆周率,r为圆半径;
正方形面积公式:s*s,其中s为边长;
勾股定理:a*a + b*b = c*c,其中a/b分别为直角三角形的两个直角边,c为斜边。
2. 计算方法
考虑下图,边长为r的正方形内嵌了一个以r为半径的1/4圆。
InsideCircle面积 = 以r为半径的圆面积 / 4 = π*r*r/4
正方形面积 = r*r
所以, InsideCircle面积 / 正方形面积 = (π*r*r/4) / (r*r) = π/4
面由线组成,线由点组成。因此,如果有若干点均匀落入到正方形中,那么落入InsideCircle的点的个数占总数的比率也将会是π/4,由此将会统计出π的值。
二、实战篇
1. 散弹枪计算
具体方式为:制作一个如上图一样正方形木板,用散弹枪对着它一顿乱扫,最后统计弹孔个数和落点,从而得出π的值。
事实上,真的有研究人员做过这个脑洞大过黑洞的实验,他们在 30857 个样本中得到了 3.13 这个还算不错的结果。
详见:http://www.techug.com/compute-pi-with-gun
2. Java随机数计算
作为一个码农,当然玩不起散弹枪这种高级玩具,那么接下来就以代码来玩一把。
具体思路是这样的:r直接取值为1.0,还需要定义一个落在正方形中的所有点的个数PointNumber,每一个点都有一个坐标(x,y),x,y取值为0.0-1.0,利用Java随机数生成每个点,然后用勾股定理判断该点是落在圆内还是圆外,并统计落在圆内的点的个数InsideCircleNumber,那么π=InsideCircleNumber/PointNumber*4。当然,如果只计算一次的话,可能误差会较大,可以再增加一个计算次数CalcTimes,然后求平均值。
按照这样的思路的计算结果如下:
PointNumber | CalcTimes | π | 最接近π的值 |
10000 | 10000 | 3.141617279999959 | 3.1416 |
100000 | 10000 | 3.1415569599999684 | 3.1416 |
1000000 | 10000 | 3.1415845499999953 | 3.141592 |
10000000 | 10000 | 3.1415924761886806 | 3.1415928 |
附源代码:
package com.test.pai; import org.apache.commons.lang.math.RandomUtils; public class CalcPai public static double CalcPaiByPointNumber(long num) double pai = inCircleNum * 4 / num; return pai; public static void main(String[] args) double pai = CalcPai.CalcPaiByPointNumber(num); System.out.println("No." + i + "/" + times + "\t" + pai + "\t" + currResult.getCurrPai() + "\t" } } |
转载于:https://blog.51cto.com/yuanhuan/1614051