对于圆周率率的求法有很多,最近看到一个Spark的例子使用了map和reduce的方法来求一个圆周率的近似值。这个算法的思想是这样的:
- 半径为r的圆的面积CA = π × r × r
- 这个园的外切正方形的面积SA = 4 × r × r
- π = CA / r / r = CA × 4 / SA
根据上面的推导,我们只要知道圆形和正方形的面积之比就行了。然后我们在这个正方形的面积内随机生成足够多的点,用落在圆内的点数除以总的点数就可以得到一个近似的比值了。当然随机值的数目越多,得到的结果就会越精确。
具体程序的实现上,我们假设圆心为(1,1)的圆的半径为1,所以正方形的边长就为2. 然后使用map来生成一个随机数并判断这个数是否在圆内,通过reduce来统计圆内的数目。这个算法是使用Spark在集群上进行计算的,所以我们创建多个工作在不同线程上的Observable对象来模拟多个任务,在最后使用zip操作符收集所有任务的计算结果并求平均值。代码如下:
1 | private Observable<Double> createObservable(final int num) { |
编写testcase来测试一下我们的程序:
1 |
|
最后的运行结果如下,创建的点数越多,得到的结果越跟真实值相近,当然计算所花费的时间就会越多。
1 | V:3.143012 |