用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]