q3256 发表于 2016-12-12 09:54:20

用Hadoop扔飞镖算Pi——献给圆周率日

  众所周知,在一个正方形上抛飞镖,假设有一个半径为正方形边长的1/4圆,则抛的飞镖在1/4圆内的概率为1/4圆面积除以正方形面积,即(pi*r^2 /4)/r^2,假设抛飞镖在圆内的概率为n,则pi=4n,通过蒙特卡洛模拟则可算出一个较接近的pi。由于频率是不断接近概率的,因此必须抛很多次飞 镖,这里采用了Hadoop去模拟。
1. [代码]MapReduce的mainRunner忽略,大家可根据需要改下输入输出KeyValue的意义    
01// Mapper
02public class PieMapper extends
03        Mapper<IntWritable, LongWritable, LongWritable, LongWritable> {
04    private Random random = new Random();
05    @Override
06    protected void map(IntWritable key, LongWritable value, Context context)
07            throws IOException, InterruptedException {
08        long inside = 0;
09        for (int i = 0; i < value.get(); i++) {
10            double a = random.nextDouble();
11            double b = random.nextDouble();
12            if ((a * a + b * b) <= 1) {
13                inside++;
14            }
15        }
16        context.write(value, new LongWritable(inside));
17    }
18}
19// 输入为第几行(忽略)+本行所算的抛飞镖次数
20 
21// Reducer
22public class PieReducer extends
23        Reducer<LongWritable, LongWritable, LongWritable, DoubleWritable> {
24    @Override
25    protected void reduce(LongWritable key, Iterable<LongWritable> values,
26            Context context) throws IOException, InterruptedException {
27        long total = 0;
28        long inside = 0;
29        for (LongWritable value : values) {
30            total += key.get();
31            inside += value.get();
32        }
33        context.write(key, new DoubleWritable(
34                4 * (inside / total)));
35    }
36}
37 
38// 代码应该比较清楚,输出为抛的总次数所对应的算出的圆周率,可以用来对比抛N次所得到的精度。当然Double是非常不精确的,要想更精确则需要重新实现大的浮点类型
页: [1]
查看完整版本: 用Hadoop扔飞镖算Pi——献给圆周率日