繁体   English   中英

使用带有线程参数的Gregory-Leibniz的pi值错误

[英]Error on pi value using the Gregory-Leibniz with thread parameter

我试图使用多线程并指定要使用的线程数在Java中实现Gregory-Leibniz。 我失败了,因为最后PI给我的价值是43。

有人可以帮我吗? 如果我不必输入线程数,那很好,但是输入线程数会破坏我的程序,并且不确定如何解决这个问题。

    System.out.print("Insert Number of threads:");
    int numetothreads = scannerObj.nextInt();
    System.out.println("Nº threads : " + numetothreads);
    //https://stackoverflow.com/questions/949355/executors-newcachedthreadpool-versus-executors-newfixedthreadpool
    ExecutorService es = Executors.newFixedThreadPool(numetothreads);
    long ti = System.currentTimeMillis();


    //separate in 4 and join after
    Future<Double> parte1 = es.submit(new CarlzParalel(1, 100000000));
    Future<Double> parte2 = es.submit(new CarlzParalel(100000001, 200000000));
    Future<Double> parte3 = es.submit(new CarlzParalel(200000001, 300000000));
    Future<Double> parte4 = es.submit(new CarlzParalel(400000001, 500000000));

这就是即时通讯用来指定线程数的方法

public class CarlzParalel implements Callable<Double> {

    private int begin;
    private int end;

    public CarlzParalel(int begin, int end) {
        this.begin= begin;
        this.end = end;
    }

    public Double call() throws Exception {
        double sum = 0.0;
        double fator;
        for (int i = begin; i <= end; i++) {
            if (i % 2 == 0) {
                fator = Math.pow(1.0, i + 1);
            } else {
                fator = Math.pow(1.0, -i + 1);
            }
            sum += fator / (2.0 * (double) i - 1.0);
        }

        return sum;
    }


    public static void main(String[] args) throws InterruptedException, ExecutionException {
        //cria um pool de threads para realizar o cálculo
        Scanner scannerObj = new Scanner(System.in);

        //System.out.println("Nº threads : " + listathreads);
        //ExecutorService es = Executors.newCachedThreadPool();
        System.out.print("Insert number of threads:");
        int numetothreads = scannerObj.nextInt();
        System.out.println("Nº threads : " + numetothreads);
        //https://stackoverflow.com/questions/949355/executors-newcachedthreadpool-versus-executors-newfixedthreadpool
        ExecutorService es = Executors.newFixedThreadPool(numetothreads);
        long ti = System.currentTimeMillis();


        //separate in 4 then join all
        Future<Double> parte1 = es.submit(new CarlzParalel(1, 100000000));
        Future<Double> parte2 = es.submit(new CarlzParalel(100000001, 200000000));
        Future<Double> parte3 = es.submit(new CarlzParalel(200000001, 300000000));
        Future<Double> parte4 = es.submit(new CarlzParalel(400000001, 500000000));

        /*
        Future<Double> parte1 =  es.submit(new CarlzParalel(1,100000000));
        Future<Double> parte2 = es.submit(new CarlzParalel(100000001,200000000));
        Future<Double> parte3 = es.submit(new CarlzParalel(200000001,300000000));
        Future<Double> parte4 = es.submit(new CarlzParalel(300000001,400000000));*/

        //join the values
        double pi = 4.0 * (parte1.get() + parte2.get() + parte3.get() + parte4.get());

        es.shutdown();

        System.out.println("Pi is " + pi);
        long tf = System.currentTimeMillis();
        long tcc = tf-ti;
        System.out.println("Time with concurrency " + tcc);

        ti = System.currentTimeMillis();

        //separate in 4 then join all without concurrency

        try {
            Double parteA = (new CarlzParalel(1, 100000000)).call();
            Double parteB = (new CarlzParalel(100000001, 200000000)).call();
            Double parteC = (new CarlzParalel(200000001, 300000000)).call();
            Double parteD = (new CarlzParalel(400000001, 500000000)).call();
            pi = 4.0 * (parteA + parteB + parteC + parteD);
        } catch (Exception e) {
            e.printStackTrace();
        }

        //join them all

        System.out.println("PI is " + pi);
        tf = System.currentTimeMillis();
        long tsc = tf - ti;
        double divisao = (double) tcc / (double) tsc;
        double gain = (divisao) * 100;
        System.out.println("Time with no concurrency " + tsc);
        System.out.println("Gain % – TCC/TSC * 100 = " + gain + " %");
        System.out.println("Number of processores: " + Runtime.getRuntime().availableProcessors());


    }
}
Insert number of threads:4
Nº threads : 4
Pi is 43.41189321992768
Time wasted with concurrency 10325
Pi is 43.41189321992768
Time wasted without concurrecy 42131
gainz% – TCC/TSC * 100 = 24.506895160333247 %
Nº threads: 4

假设您正在尝试计算公式:

在此处输入图片说明

然后,您的求和方法看起来不正确。

您拥有的分子代码将始终返回1。如果尝试使其返回1或-1,则有几种方法可以实现,例如:

   double numerator = n % 2 == 0 ? 1 : -1;

分母在我看来也错了,我可能会喜欢这样的东西:

   double denominator = n * 2 + 1;

并且从1而不是0开始,需要修改for循环以从输入参数中减去1。 这些方法的总和如下所示:

    public Double call() throws Exception {
        double sum = 0.0;
        for (int i = begin - 1; i < end; i++) {
            double numerator = i % 2 == 0 ? 1 : -1;
            double denominator = i * 2 + 1;
            sum += numerator / denominator;
        }
        return sum;
    }

然而

  1. 您输入的内容缺少300000001至400000000的范围

  2. double并不真正适合任何精度。 开箱即用,您可以使用BigDecimal但这显然至少要慢一个因子。

关于精度和双打,如果以下结果有所不同,我不会感到惊讶:

    double pi = 4.0 * (parte1.get() + parte2.get() + parte3.get() + parte4.get());
    System.out.println("Pi is " + pi);


    // reverse the order of the sum
    double 4.0 * (parte4.get() + parte3.get() + parte2.get() + parte1.get());
    System.out.println("Pi is " + pi);

不知道您的call数学有什么问题,但这当然是问题所在。

public static class CarlzParallel implements Callable<Double> {

    private int begin;
    private int end;

    public CarlzParallel(int begin, int end) {
        this.begin = begin;
        this.end = end;
    }

    public Double call() throws Exception {
        double sum = 0.0;
        for (int i = begin; i <= end; i++) {
            double dividend = (i % 2) == 0 ? -1 : 1;
            double divisor = (2 * i) - 1;
            sum += dividend / divisor;
        }
        return sum;
    }

}

private void test() {
    ExecutorService es = Executors.newFixedThreadPool(4);
    //separate in 4 then join all
    Future<Double> parte1 = es.submit(new CarlzParallel(1, 100000000));
    Future<Double> parte2 = es.submit(new CarlzParallel(100000001, 200000000));
    Future<Double> parte3 = es.submit(new CarlzParallel(200000001, 300000000));
    Future<Double> parte4 = es.submit(new CarlzParallel(400000001, 500000000));
    double π = 0;
    try {
        es.shutdown();
        while(!es.awaitTermination(5, TimeUnit.SECONDS)) {
            System.out.println("Waiting ...");
        }
        π = 4.0 * (parte1.get() + parte2.get() + parte3.get() + parte4.get());
    } catch (Exception e) {
        e.printStackTrace();
    }
    System.out.println(π);
}

版画

3.141592650755993

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM