用hadoop计算PI值

本文介绍了使用Hadoop通过Quasi-Monte Carlo算法估算PI值的原理,引用了斯坦福大学的文章,阐述了如何通过投掷飞镖模拟,利用Halton sequence确保随机性和均匀性。在Hadoop环境中,通过运行特定命令,根据投掷次数的增加提高计算精度。
摘要由CSDN通过智能技术生成
      摘要:最近研究hadoop的一个例子,计算PI值,本以为hadoop不适合这种密集型的计算,却发现了在hadoop自带的examples里,竟然有PiEstimator这个例子,于是深入研究一下,首先感谢博主http://thinkinginhadoop.iteye.com/blog/710847

 

一、计算PI值的方式与原理

      百度一下,计算PI的方法还真不少。但在hadoop examples代码中的注释写的是:是采用 Quasi-Monte Carlo 算法来估算PI的值。 

      维基百科中对Quasi-Monte Carlo的描述比较理论,好多难懂的公式。 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是Hadoop计算Pi的源代码及注释: ```java // PiMapper.java import java.io.IOException; import java.util.Random; import org.apache.hadoop.io.*; import org.apache.hadoop.mapreduce.*; public class PiMapper extends Mapper<Object, Text, IntWritable, IntWritable> { private final static IntWritable one = new IntWritable(1); private static Random rndm = new Random(); public void map(Object key, Text value, Context context) throws IOException, InterruptedException { int numThrows = 10000; // 每个Mapper的投掷次数 int inCircle = 0; // 落在圆内的次数 for (int i = 0; i < numThrows; i++) { // 在 [-1, 1] 的范围内随机生成一个点 double x = 2 * rndm.nextDouble() - 1.0; double y = 2 * rndm.nextDouble() - 1.0; // 判断该点是否落在圆内 if (x * x + y * y <= 1.0) { inCircle++; } } // 将落在圆内的次数作为Key,1作为Value写入Context context.write(new IntWritable(inCircle), one); } } ``` ```java // PiReducer.java import java.io.IOException; import org.apache.hadoop.io.*; import org.apache.hadoop.mapreduce.*; public class PiReducer extends Reducer<IntWritable, IntWritable, IntWritable, DoubleWritable> { private DoubleWritable result = new DoubleWritable(); public void reduce(IntWritable key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException { int sum = 0; int count = 0; // 统计Key对应的Value的总和 for (IntWritable val : values) { sum += val.get(); count++; } // 计算Pi的近似 double pi = ((double) sum / (double) count) * 4.0; // 将近似作为Value写入Context result.set(pi); context.write(key, result); } } ``` ```java // PiDriver.java import java.io.IOException; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.*; import org.apache.hadoop.mapreduce.*; public class PiDriver { public static void main(String[] args) throws Exception { Configuration conf = new Configuration(); Job job = Job.getInstance(conf, "Pi Estimation"); // 设置Mapper job.setMapperClass(PiMapper.class); job.setMapOutputKeyClass(IntWritable.class); job.setMapOutputValueClass(IntWritable.class); // 设置Reducer job.setReducerClass(PiReducer.class); job.setOutputKeyClass(IntWritable.class); job.setOutputValueClass(DoubleWritable.class); // 设置InputFormat job.setInputFormatClass(TextInputFormat.class); // 设置OutputFormat job.setOutputFormatClass(TextOutputFormat.class); // 设置输入路径和输出路径 FileInputFormat.addInputPath(job, new Path(args[0])); FileOutputFormat.setOutputPath(job, new Path(args[1])); // 提交作业并等待完成 System.exit(job.waitForCompletion(true) ? 0 : 1); } } ``` 注释: 1. `PiMapper`类是一个Mapper类,它继承自`Mapper<Object, Text, IntWritable, IntWritable>`。它的输入键是`Object`,输入是`Text`,输出键是`IntWritable`,输出是`IntWritable`。 2. 在`PiMapper`类中,我们首先定义了一个`IntWritable`类型的常量`one`,它的为1。接着,我们使用`java.util.Random`类创建了一个随机数生成器`rndm`。 3. `map`方法是`Mapper`类中的一个重要方法,它的作用是将输入键对转换为输出键对。在`PiMapper`类中,我们将每个Mapper的投掷次数设置为10000,然后在这个范围内随机生成一个点,判断该点是否落在圆内。如果是,我们将`inCircle`变量加1。最后,将落在圆内的次数作为Key,1作为Value写入Context。 4. `PiReducer`类是一个Reducer类,它继承自`Reducer<IntWritable, IntWritable, IntWritable, DoubleWritable>`。它的输入键是`IntWritable`,输入是`IntWritable`,输出键是`IntWritable`,输出是`DoubleWritable`。 5. 在`PiReducer`类中,我们首先定义了一个`DoubleWritable`类型的变量`result`。在`reduce`方法中,我们统计了Key对应的Value的总和和Value的数量。然后,根据公式计算Pi的近似,将近似作为Value写入Context。 6. `PiDriver`类是一个驱动程序。在`main`方法中,我们首先创建了一个`Configuration`对象和一个`Job`对象。然后,我们设置了Mapper、Reducer、InputFormat和OutputFormat。接着,我们设置了输入路径和输出路径。最后,我们提交作业并等待完成。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值