Benjamin Bouillé bio photo

Benjamin Bouillé

IT consultant

Email Twitter Google+ LinkedIn Github Stackoverflow

Did you ever wonder how many decimals of Pi your computer could compute ? Well using one (of many) algorithms to approximate Pi, I got a surprising answer with the following java code.

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import java.math.BigDecimal;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.BrokenBarrierException;
/**
*
* @author onnetz
*/
public class ArctanPi {

final BigDecimal FOUR = new BigDecimal("4");
BigDecimal arctan1_5, arctan1_239, pi;

final int roundingMode = BigDecimal.ROUND_HALF_EVEN;
final int digits;
Thread[] threads;
int numProcessors;
CyclicBarrier cb;

public ArctanPi(int digits) {
this.digits = digits;
numProcessors = Runtime.getRuntime().availableProcessors();
// numProcessors = 2;

}

public void startPi() {
threads = new Thread[numProcessors];
cb = new CyclicBarrier(numProcessors+1, new Runnable() {
public void run() {
finishUp();
}
});

for(int a = 0; a < numProcessors; a++) {
threads[a] = new ArctanPi.MyThreads();
threads[a].start();
}
try {
cb.await();
} catch(InterruptedException ie) {

} catch(BrokenBarrierException be) {

}
}

/**
* Compute the value of pi to the specified number of
* digits after the decimal point. The value is
* computed using Machin's formula:
*
* pi/4 = 4*arctan(1/5) - arctan(1/239)
*
* and a power series expansion of arctan(x) to
* sufficient precision.
*/
public void computePi() {
try {
arctan1_5 = arctan(5, digits+5);
arctan1_239 = arctan(239, digits+5);

cb.await();
} catch(InterruptedException ie) {
ie.printStackTrace();
} catch(BrokenBarrierException be) {
be.printStackTrace();
}

}

public void finishUp() {
pi = arctan1_5.multiply(FOUR).subtract(
arctan1_239).multiply(FOUR);
pi.setScale(digits,
BigDecimal.ROUND_HALF_UP);
}

/**
* Compute the value, in radians, of the arctangent of
* the inverse of the supplied integer to the specified
* number of digits after the decimal point. The value
* is computed using the power series expansion for the
* arc tangent:
*
* arctan(x) = x - (x^3)/3 + (x^5)/5 - (x^7)/7 +
* (x^9)/9 ...
*/
public BigDecimal arctan(int inverseX,
int scale)
{
BigDecimal result, numer, term;
BigDecimal invX = BigDecimal.valueOf(inverseX);
BigDecimal invX2 =
BigDecimal.valueOf(inverseX * inverseX);

numer = BigDecimal.ONE.divide(invX,
scale, roundingMode);

result = numer;
int i = 1;
do {
numer =
numer.divide(invX2, scale, roundingMode);
int denom = 2 * i + 1;
term =
numer.divide(BigDecimal.valueOf(denom),
scale, roundingMode);
if ((i % 2) != 0) {
result = result.subtract(term);
} else {
result = result.add(term);
}
i++;
} while (term.compareTo(BigDecimal.ZERO) != 0);
return result;
}

/**
* @param args the command line arguments
*/
public static void main(String[] args) {
int digits = 100000;
ArctanPi m = new ArctanPi(digits);
long stime = System.currentTimeMillis();
m.startPi();
long etime = System.currentTimeMillis();
System.out.println((double)(etime - stime)/1000 +
" secs for " + digits + " digits.");
}

class MyThreads extends Thread {
public void run() {
computePi();
}
}

}

##Compilation

javac ArctanPi.java

##Running

java ArctanPi

##Results

Nb of
processor
result
1  20.717 secs for 100.000 digits.
2  20.458 secs for 100.000 digits.
3  25.696 secs for 100.000 digits.
4 27.938 secs for 100.000 digits.

More processor doesn’t not necessarily mean better results.

source