【问题标题】:Error on pi value using the Gregory-Leibniz with thread parameter使用带有线程参数的 Gregory-Leibniz 的 pi 值错误
【发布时间】:2019-11-03 00:17:11
【问题描述】:

我正在尝试使用多线程在 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

【问题讨论】:

  • 如果你“组合”期货,你不应该除以得到这 4 个值的平均值吗?

标签: java multithreading


【解决方案1】:

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

那么你的求和方法看起来不正确。

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

【讨论】:

  • 非常感谢您的帮助。要尝试改进我的代码,BigDecimal 看起来是个好主意,因为我需要更大的间隔。谢谢!
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-02-05
    • 2019-12-11
    • 1970-01-01
    • 1970-01-01
    • 2020-05-21
    • 2012-09-01
    • 1970-01-01
    • 2018-07-25
    相关资源
    最近更新 更多