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

时间:2019-06-20 07:58:58

标签: java multithreading

我正在尝试使用多线程并指定要使用的线程数在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

2 个答案:

答案 0 :(得分:3)

假设您要计算公式:

enter image description here

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

您拥有的分子代码将始终返回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);

答案 1 :(得分:0)

不确定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