Welcome to the Java Programming Forums

The professional, friendly Java community. 21,500 members and growing!

The Java Programming Forums are a community of Java programmers from all around the World. Our members have a wide range of skills and they all have one thing in common: A passion to learn and code Java. We invite beginner Java programmers right through to Java professionals to post here and share your knowledge. Become a part of the community, help others, expand your knowledge of Java and enjoy talking with like minded people. Registration is quick and best of all free. We look forward to meeting you.

>> REGISTER NOW TO START POSTING

Members have full access to the forums. Advertisements are removed for registered users.

# Thread: Calculating Pi to more digits?

1. ## Calculating Pi to more digits?

Hey guys! So I have been messing around with calculating pi and I have gotten to the point where I have a loop running from 0 to long.max value. I am using the fallowing infinite series:
`pi = 4/1 + 4/3 - 4/5 + 4/7 ...`
I am wondering a few things. First of all, I tried using BigDecimal and BigInteger to do this and it didn't really work out... I am wondering, how do I convert this:
```double pi = 0.0;
long divisor = 1;
boolean positive = false;

for(long i = 0; i < Long.MAX_VALUE; i++)
{
double n = ((double)4 / (double)divisor);
if(positive)
pi -= n;
else
pi += n;
positive = !positive;
divisor += 2;
}

print("Pi calculated as: " + pi);```
To use BigInteger/Decimal? Also, are there any more accurate infinite series' that are more accurate AND are just as easy or almost as easy to implement?  Reply With Quote

3. ## Re: Calculating Pi to more digits?

Read the API for the BigInteger class and see which methods suit your needs.
Post the code with your attempt if you have problems.
Ask a specific question if you have one, right now your question just kind of asks for someone to convert it to use BigInteger for you.  Reply With Quote

4. ## Re: Calculating Pi to more digits?

And for an overview of series approximations Wikipedia is a good first stop.

A factoid for anyone too idle to follow the link: the currently calculated precision is 10 trillion digits using Chudnovsky's algorithm. It looks like it should be reasonably easily implemented. Certainly more easily implemented than understood!  Reply With Quote

5. ## Re: Calculating Pi to more digits?

Due to my age, I haven't even learned most of that maths... I have no idea what the majority of that stuff means. Thus, I have no idea how to implement it. One question that isn't related to the algorithm however, how could I implement something that would calculate pi with multiple threads or multiple workers? I have ideas but I don't know how I could really make them work together properly. I would love to figure that out.  Reply With Quote

6. ## Re: Calculating Pi to more digits?

jps called it correctly, I think. Rather than threads, think about how you might implement the formula you have using BigDecimal/Integer.

To begin with write some programs that simply add/subtract/multiply/divide decimal values. Once those are working as you intend you can use the arithmetic operations on decimal values in your pi program.

Ask if you get stuck. It really doesn't matter what code you come up with, but people can only really help with that code. If someone posts *their* pi calculating code, that's just robbed you of the fun of writing your own.  Reply With Quote

7. ## Re: Calculating Pi to more digits? Originally Posted by sci4me ...BigDecimal...
That's probably a good thing to investigate, since you are wanting more precision in the terms than Java's built-in double precision variables can give you. Originally Posted by sci4me ...and BigInteger to do this and it didn't really work out...
I don't see the need for BigInteger. Every term is a floating point number. When you add successive terms you get an approximation that is a floating point number. So, just do everything with floating point arithmetic. Concentrate on BigDecimal (or other arbitrary precision floating point packages that you might run across).

What do you mean it didn't "work out"? It "works out" if you "do it right." Originally Posted by sci4me I am wondering, how do I convert this...

OK, I'll give it a shot:
• Create BigDecimal objects for numerator, denominator, sum, and term with initial values 4.0, 1.0, 0.0, and 4.0

• You very well might find use for a BigDecimal object initialized to 2.0, so that you can add 2.0 to the denominator each time through the loop. (I would probably call it bigTwo, or some such thing.)

• Declare a boolean variable positiveSign that will make it easy to alternate the sign of the term that contributes to the sum each time through the loop. initialize it to true, since the first term will be added to sum inside the loop.

• Decide how many terms you would like to use in your approximation. Start with a small number so that you can verify the accuracy of the term and the cumulative sum at each step of the program.

• Decide how many decimal places of precision for which you want the divisions to be approximated and create a MathContext object for this value.

Here's pseudo-code for the main() method:

```Declare and initialize int variables numTerms and precision.

Create a MathContext object with your value of precision.

Declare and initialize BigDecimal objects
bigTwo        Initial value 2.0
sum           Initial value 0.0
numerator     Initial value 4.0
denominator   Initial value 1.0
term          Initial value numerator divided by denominator

Declare and initialize the boolean variable:
positiveSign  Initial value true

Here's the loop:
for (int i = 0; i < numTerms; i++)
BEGIN LOOP
IF positiveSign THEN
sum = sum plus term  // Use BigDecimal add() method
ELSE
sum = sum minus term // Use BigDecimal subtract() method
END IF

Print out value of sum.

// Calculate value of next term.  Note that for alternating
// convergent series, truncation error is less than or equal
// to the absolute value of the next term.

denominator = denominator plus 2  // Use BigDecimal add(bigTwo)
term = numerator divided by denominator // Use BigDecimal divide() with mc context
Print value of term.  (This is an upper bound of the error of the sum so far.)

Set positiveSign equal to !positiveSign
END LOOP```

Now, suppose we want 10 decimal digit precision to be maintained for the division operations, and suppose we want to print the first four partial sums

The output might look like:
```Partial sum 1:
Approx: 4
|Err| < 1.333333333

Partial sum 2:
Approx: 2.666666667
|Err| < 0.8

Partial sum 3:
Approx: 3.466666667
|Err| < 0.5714285714

Partial sum 4:
Approx: 2.8952380956
|Err| < 0.4444444444```

It's very important that you verify the validity of these values before going on to bigger and better things.

If you like it so far (that is, if you think it is giving the results that you expected), then, try something like precision = 100 decimal digits and ten thousand terms.

Here are the last few of the 10000 partial sums:
```Partial sum 9997:
Approx: 3.1416926835985457141409486174398088488002669437238313470218194294878764930799823190509708376226708769092
|Err| < 0.0002000500125031257814453613403350837709427356839209802450612653163290822705676419104776194048512128032

Partial sum 9998:
Approx: 3.1414926335860425883595032560994737650293242080399103667767581641715474108094146771404932182178196641060
|Err| < 0.0002000300045006751012651897784667700155023253488023203480522078311746762014302145321798269740461069160

Partial sum 9999:
Approx: 3.1416926635905432634607684458779405350448265333887126871248103720027220870108448916726730451918657710220
|Err| < 0.0002000100005000250012500625031251562578128906445322266113305665283264163208160408020401020051002550128

Partial sum 10000:
Approx: 3.1414926535900432384595183833748153787870136427441804605134798054743956706900288508706329431867655160092
|Err| < 0.0001999900004999750012499375031248437578121093945302734863256837158142092895355232238388080595970201490```

See how it goes?

The program has done a lot of work. (Who cares? That's why we have computers, right? Let them do the work.)

However...

After ten thousand terms, the approximation is only correct to four significant decimal digits.

The problem isn't with the "accuracy" of the infinite series you are using. It's "accurate." The problem is that it will take a lot of terms (a whole lot of terms) to converge to a value that has more precision than the 16 or 17 significant decimal digits that you get with double precision Java variables.

Exercise for the student:

How many terms of the series will be required to get an approximate value of Pi that is accurate to 20 significant decimal digits.

That's 19 decimal places accuracy.

Question:
Given that the absolute error after n terms is bounded by the value of the next term (i.e. 4/(2*n+1)), how many terms will be required to guarantee that the error is less than 0.5 times 10 to the -19 power?

Short answer:
A bunch.

Intermediate answer:
A really big bunch.

Next question:
Is there a better way?

Answer:
There are about a million ways. Maybe more. It happens that your series, equal to the Taylor series expansion of 4*arctan(1.0), is one of the slowest of them all. Really slow.

People have been developing faster-converging approximations for hundreds of years. Maybe more. If you are really interested, then do some research and knuckle down to learning some math.

Maybe start here: Numerical Approximations of Pi

If you think it's better to spend your time doing something else until you have been exposed to enough mathematical rigor to read the literature, then that's OK too.

Cheers!

Z  Reply With Quote