All pastes #1292089 Raw Edit

PiChudnovskymultithread

public java v1 · immutable
#1292089 ·published 2008-12-23 06:23 UTC
rendered paste body
import org.apfloat.*;import java.io.IOException;import java.util.Scanner;import java.io.File;/** * * @author Jake Gunter */public class PiChudnovskyMultithread {        /**     * the precision of the calculation; it is set later     */    static long precision = 1;        /**     * the scanner used throughout the program     */    Scanner in = new Scanner(System.in);        /**     * Pi, guaranteed correct (for testing purposes)     */    private String piCorrect;        //simple constructor    public PiChudnovskyMultithread() throws IOException {        piCorrect = readPiFile();    }        public String readPiFile() throws IOException {        Scanner fin = new Scanner(new File("pi.txt"));        String piTmp = "";        while(fin.hasNext())             piTmp += fin.nextLine();        return piTmp;    }    public void validatePi(Apfloat pi) {        String piStr = pi.toString(true);        int smallerLen = piStr.length() < piCorrect.length() ? piStr.length() : piCorrect.length();        int digitsCorrect = 0;        String userPiCorrect = "";        for(int i=0;i<smallerLen;i++) {            char correct = piCorrect.charAt(i);            char user = piStr.charAt(i);            if (correct == user) {                digitsCorrect++;                userPiCorrect += user;            }            else break;        }        System.out.println(digitsCorrect-1 + " digits correct:");        System.out.println(userPiCorrect);    }    public static Apfloat factorial(Apfloat num) {        if (num.compareTo(new Apfloat(0)) == 0) return Apfloat.ONE;        Apfloat factorialized = num;        for(Apfloat i=num;i.compareTo(new Apfloat(0))>0;i=i.subtract(new Apfloat(1))) {            Apfloat x = i.compareTo(new Apfloat(1)) == 0 ? new Apfloat(0) : new Apfloat(1);            factorialized = factorialized.multiply(i.subtract(x));        }        return factorialized;    }    public static Apfloat inverse(Apfloat num) {        return new Apfloat(1).divide(num);    }    public static Apfloat negpow(Apfloat a, Apfloat b) {        if(b.mod(new Apfloat(2)).intValue() == 0) {            return ApfloatMath.pow(a.negate(),b);        }        else return ApfloatMath.pow(a.negate(), b).negate();    }        /**     * This method handles the thread scheduling and the final summation of pi.     * First, it checks the number of available processors with a call to     * <code>Runtime.getRuntime().availableProcessors()</code>. Then it creates     * an array of {@link chudThread} that will do the actual calculation.     * <p>     * Based on a user input of the number of iterations, it spreads that out     * over all available <code>chudThread</code>, and sets the field <code>     * precision</code> according to the number of calculations.     * It also times the calculation.     * <p>     * After all threads have finished calculating, it sums the partial sums,     * and carries out the final steps needed to calculate pi. Then it displays     * pi, along with the amount of time taken for the calculation.     *      * @throws java.lang.InterruptedException     * @throws java.io.IOException     */    public void calculatePi() throws InterruptedException, IOException {        int numProcs = Runtime.getRuntime().availableProcessors();        chudThread[] calculators = new chudThread[numProcs];        long start = 0;        System.out.print("How many iterations? ");        int procMult = Integer.parseInt(in.nextLine()) / numProcs;        while (procMult <= 0) {            System.out.println("That's not a valid number of iterations!");            System.out.print("How many iterations? ");            procMult = (in.nextInt()) / numProcs;        }        precision = procMult * numProcs * 14 + 1 + (procMult * numProcs)/10;        System.out.println(precision);        for(int i=0;i<numProcs;i++) {            calculators[i] = new chudThread(start, start+=procMult);        }        System.out.println("Calculating...");        long startTime = System.currentTimeMillis();        for(int i=0;i<numProcs;i++) {            calculators[i].start();        }        for(int i=0;i<numProcs;i++) {            calculators[i].join();        }        Apfloat pi = new Apfloat(0,precision);        for (int i=0;i<numProcs;i++) {            pi = pi.add(calculators[i].piPart);        }        pi = pi.multiply(new Apfloat(12,precision));        pi = inverse(pi);        new PiChudnovskyMultithread().validatePi(pi);        long endTime = System.currentTimeMillis();        System.out.println("Calculation took " + ((double)(endTime - startTime) / 1000) + " seconds.");    }        /**     * This subclass is the thread that calculates a partial sum of pi from a     * specified start iteration to a specified end iteration. The calculation     * loop algorithm is based on the Chudnovsky brothers' formula for pi.     */    static class chudThread extends Thread {        /**         * This thread's partial sum         */        private Apfloat piPart = new Apfloat(0,precision);                /**         * the start iteration (inclusive)         */        private long start;                /**         * the end iteration (exclusive)         */        private long end;                /**         * The constructor.         *          * @param startI the starting iteration         * @param endI the ending iteration         */        public chudThread(long startI, long endI) {            start = startI;            end = endI;        }        /**         * This method sums pi from the start iteration to the end iteration.         * It stores the result in the field <code>piPart</code>.         */        @Override        public void run() {            Apfloat x = new Apfloat(0,precision);            Apfloat y = new Apfloat(0,precision);            Apfloat a = new Apfloat(0,precision);            Apfloat b = new Apfloat(0,precision);            Apfloat c = new Apfloat(0,precision);            Apfloat bn1 = new Apfloat(-1,precision);            Apfloat b6 = new Apfloat(6,precision);            Apfloat b13591409 = new Apfloat(13591409,precision);            Apfloat b545140134 = new Apfloat(545140134,precision);            Apfloat b3 = new Apfloat(3,precision);            for(Apfloat i=new Apfloat(start,precision);i.compareTo(new Apfloat(end,precision))<0;i=i.add(new Apfloat(1))) {                 a = negpow(bn1,i);                 b = factorial((b6.multiply(i)));                 c = b13591409.add(b545140134.multiply(i));                 x = a.multiply(b.multiply(c));                 a = factorial(b3.multiply(i));                 b = ApfloatMath.pow(factorial(i),3);                 c = new Apfloat(3.0/2.0,precision).add(new Apfloat(3,precision).multiply(i));                 y = a.multiply(b).multiply(ApfloatMath.pow(new Apfloat(640320,precision),c));                 piPart = piPart.add(x.divide(y));            }        }    }    public static void main(String[] args) throws InterruptedException, IOException {        new PiChudnovskyMultithread().calculatePi();    }}