HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Better performance in calculating E

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
calculatingperformancebetter

Problem

Can you give me some performance advice on how to optimize the time of execution of the following calculation of E?

package calculatee;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;

public class CalculateE {
 static long start1 = System.nanoTime();

 public static BigDecimal factorial(int x) {
    BigDecimal prod = new BigDecimal("1");
    for (int i = x; i > 1; i--) {
        prod = prod.multiply(new BigDecimal(i));
    }
    return prod;
 }

 public static void main(String[] args) {
    BigDecimal e = BigDecimal.ONE;
    for (int i = 1; i < 1000; i++) {
        e = e.add(BigDecimal.valueOf(Math.pow(3 * i, 2) + 1).divide(factorial(3 * i),new MathContext(10000, RoundingMode.HALF_UP)));
    }
    System.out.println("e = " + e);
    long stop = System.nanoTime();
    long diff = stop - start1;
    System.out.println(diff + " ns");
 }

}


The time of execution is about 3055588556 ns.

Solution

you can split up the calculation in your for loop into threads and sum up the results afterwards: here an example for 4 Threads: Use as many Threads as you have CPUs. It's important to add the result inside a synchronized block, otherwise you result could be corrupted by race conditions. I get a speed up of 50% with 4 threads compared to a single core execution.

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;

public class CalculateE {

    static long start1 = System.currentTimeMillis();

    static BigDecimal result = BigDecimal.ONE;

    public static BigDecimal factorial(int x) {
        BigDecimal prod = new BigDecimal("1");
        for (int i = x; i > 1; i--) {
            prod = prod.multiply(new BigDecimal(i));
        }
        return prod;
    }

    public static Runnable getRunner(final int from, final int to) {
        Runnable runner = new Runnable() {
            @Override
            public void run() {
                BigDecimal e = BigDecimal.ZERO;
                for (int i = from; i < to; i++) {
                    e = e.add(BigDecimal
                            .valueOf(Math.pow(3 * i, 2) + 1)
                            .divide(factorial(3 * i),
                                    new MathContext(10000, RoundingMode.HALF_UP)));
                }
                addResult(e);
            }
        };
        return runner;
    }

    public static synchronized void addResult(BigDecimal e){
        result = result.add(e);
    }

    public static void main(String[] args) throws InterruptedException {
        Runnable r1 = getRunner(1, 251);
        Runnable r2 = getRunner(251, 501);
        Runnable r3 = getRunner(501, 751);
        Runnable r4 = getRunner(751, 1000);
        Thread t1 = new Thread(r1);
        t1.start();
        Thread t2 = new Thread(r2);
        t2.start();
        Thread t3 = new Thread(r3);
        t3.start();
        Thread t4 = new Thread(r4);
        t4.start();
        t1.join();
        t2.join();
        t3.join();
        t4.join();
        System.out.println("e = " + result);
        long stop = System.currentTimeMillis();
        long diff = stop - start1;
        System.out.println(diff + " ms");
    }

}

Code Snippets

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;

public class CalculateE {

    static long start1 = System.currentTimeMillis();

    static BigDecimal result = BigDecimal.ONE;

    public static BigDecimal factorial(int x) {
        BigDecimal prod = new BigDecimal("1");
        for (int i = x; i > 1; i--) {
            prod = prod.multiply(new BigDecimal(i));
        }
        return prod;
    }

    public static Runnable getRunner(final int from, final int to) {
        Runnable runner = new Runnable() {
            @Override
            public void run() {
                BigDecimal e = BigDecimal.ZERO;
                for (int i = from; i < to; i++) {
                    e = e.add(BigDecimal
                            .valueOf(Math.pow(3 * i, 2) + 1)
                            .divide(factorial(3 * i),
                                    new MathContext(10000, RoundingMode.HALF_UP)));
                }
                addResult(e);
            }
        };
        return runner;
    }

    public static synchronized void addResult(BigDecimal e){
        result = result.add(e);
    }

    public static void main(String[] args) throws InterruptedException {
        Runnable r1 = getRunner(1, 251);
        Runnable r2 = getRunner(251, 501);
        Runnable r3 = getRunner(501, 751);
        Runnable r4 = getRunner(751, 1000);
        Thread t1 = new Thread(r1);
        t1.start();
        Thread t2 = new Thread(r2);
        t2.start();
        Thread t3 = new Thread(r3);
        t3.start();
        Thread t4 = new Thread(r4);
        t4.start();
        t1.join();
        t2.join();
        t3.join();
        t4.join();
        System.out.println("e = " + result);
        long stop = System.currentTimeMillis();
        long diff = stop - start1;
        System.out.println(diff + " ms");
    }

}

Context

StackExchange Code Review Q#49060, answer score: 3

Revisions (0)

No revisions yet.