圆周率π的近似求法 (四)

3 篇文章 0 订阅
1 篇文章 0 订阅

圆周率 π 的近似求法(四)

一个胖子

用落点概率来模拟面积比的方法,通用性强,但是准确率相对差.因此这里给出了一种针对性强的分布式求法,整体数学模型可以参考圆周率 π 的求法(二),这里引用其中方法就暂不赘述了.

引用上述方法.我们现在需要做的就是对计算进行分片,也就是 mapper ,一个整体的面积求解,可以用与y轴平行的线,按照x轴递增的规律来进行分割,最后reducer统计各部分,进行求和操作即可.

mapper部分代码如下

public class SolvingPiMapper extends Mapper<LongWritable, Text, Text, DoubleWritable> {
    /**
     * key 输入 读取文件的起始位置
     * value 输入 文件中一行的内容
     * context 输出 <k,v>形式
     */
    @Override
    protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, DoubleWritable>.Context context)
            throws IOException, InterruptedException {
        //解析从文件中读取的数据
        String[] message = value.toString().split("--");
        //获取总片数
        int totlePice = new Integer(message[0]);
        //获取当前是第几片
        int currPice = new Integer(message[1]);
        //获取总分格数
        int cell = new Integer(message[2]);
        //声明总面积
        double s = 0;
        //初始化第一次运算时的上一个 y ;currPice*1.0/totlePice*cell
        int lastY = cell-1;
        //计算面积  通过 当前是第几片来确定 x 的起始值
        for(int x =(int)Math.floor(currPice*1.0/totlePice*cell);x<(int)Math.floor((currPice+1)*1.0/totlePice*cell);x++){
            for(int y = lastY;y>=0;y-- ){
                double newX = (2*x+1)*1.0/(2*cell);
                double newY = (2*y+1)*1.0/(2*cell);
                //判断该节点是否在扇形中
                if((newX*newX+newY*newY)<=1){
                    lastY = y ;
                    s += newY/cell;
                    break ;
                }
            }

        }

        context.write(new Text("PI"),new DoubleWritable(s));
    }

}   

reducer 部分代码

public class SolvingPiReducer extends Reducer<Text, DoubleWritable, Text, DoubleWritable> {
    /**
     * name 输入的 "PI"
     * message 输入的"totle--num"
     * context 输出的<k,v>
     * 所有键位"PI"的输入都用这个方法进行处理
     */
    @Override
    protected void reduce(Text name, Iterable<DoubleWritable> message, Reducer<Text, DoubleWritable, Text, DoubleWritable>.Context context)
            throws IOException, InterruptedException {
        //累加求总面积
        double sumS = 0;
        for (DoubleWritable s : message) {
            sumS += s.get();
        }
        //输出最后结果
        context.write(name,new DoubleWritable(sumS*4));
    }
}

主类

public class SolvingPiRunner {
    //把业务逻辑相关的信息(哪个是 mapper,哪个是 reducer,要处理的数据在哪里,输出的结果放在哪里……)描述成一个 job 对象
    //把这个描述好的 job 提交给集群去运行
    public static void main(String[] args) throws Exception {
        //用户自定义输入
        System.out.println("请输入你想分的片数:");
        Scanner sc = new Scanner(System.in);
        int pice=new Integer(sc.nextLine());
        System.out.println("请输入总分格数:");
        String line=sc.nextLine();
        //按照分片生成文件(在实际环境中需要在hdfc中创建文件)
        for(int i=0;i<pice;i++){
            BufferedWriter bw = new BufferedWriter(new FileWriter(new File("D:\\hadoop\\input\\"+(i+1)+".txt")));
            bw.write(pice+"--"+i+"--"+line);
            bw.close();
        }

        //把业务逻辑相关的信息(哪个是 mapper,哪个是 reducer,要处理的数据在哪里,输出的结果放在哪里……)描述成一个 job 对象
        //把这个描述好的 job 提交给集群去运行
        Configuration conf = new Configuration();
        Job job = Job.getInstance(conf);
        //知道这个job所在jar包
        job.setJarByClass(SolvingPiRunner.class);

        job.setMapperClass(SolvingPiMapper.class);
        job.setReducerClass(SolvingPiReducer.class);
        //设置我们的业务逻辑Mapper类的输出key 和  value 的数据
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(DoubleWritable.class);
        //设置我们的业务逻辑Reducer 类的输出Key和value 的数据类型
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(DoubleWritable.class);
        //指定要处理的数据所在的位置
        FileInputFormat.setInputPaths(job, "D:\\hadoop\\input\\*.txt");
        //指定处理完成后,结果所保存的位置
        FileOutputFormat.setOutputPath(job, new Path("D:\\hadoop\\output\\result"));
        //向yarn集群提交这个job

        boolean res = job.waitForCompletion(true);
        System.exit(res?0:1);
    }
}

测试结果

输入 
    10 X 100000000
测试结果
    PI  3.1415926335938655 
用概率试验方法得到的结果
    PI  3.141599752

虽然精确度提高但是方法针对性太强无法复用.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值