Finding Pi

I’m currently on a mission to write a program that finds pi to a few thousand (or more) decimal places. So far I have encountered many problems with this.

Originally I was going to use the formula pi = sin(1 / ∞) * ∞ * 180

There are many problems with this approach. The first most obvious problem is that there is no way of finding infinity. The way to get around this is to just use a gigantic number (googolplex for example). That would give a fairly good representation of pi.

The next big problem is finding the sine this infinitely small positive number. It is impossible to find a perfect sine of this number because the sine of this number is almost definitely an irrational number. So that means any pi that you find using this method will be wildly off once you get past a few decimal places.

The other big problem is that to find the sine of a number, you have to use pi. This is true because you have have to convert the infinitely small number to radians. This number is in degrees and you have to convert to radians to find the sine of it. To convert degrees to radians, you use the formula: radians = degrees * (pi / 180)

This is basically a problem of the chicken and the egg. You need a perfect representation of pi to find a perfect representation of pi. For more about the sine problem, check out this page: http://www.homeschoolmath.net/teaching/sine_calculator.php

So with all of these problems, this is not a good way of finding pi accurately to many decimal places. However, if you try this formula with 10000 instead of ∞, then you get pi to 9 decimal places with no trouble (my calculator only has 10 digit answers).

The other way of finding pi would be to use this formula: pi / 4 = 1 – (1/3) + (1/5) – (1/7) + (1/11) – (1/13) + …….

This is a much better approach to take, because it allows easy calculation. The only problem with this approach is that it takes many many iterations of this sequence to get an accurate pi. If you try the sequence above, it gives you around 3.2…. The nice thing about computers is that they can do these types of calculations very quickly.

Putting this into action is pretty simple. Here is the source for a processing app that demonstrates this:

[[[Start Code]]]

import java.math.*;
void setup() {
 print("Welcome to the Pi calculator. The program will quit when the calculation is finished.");
}
void draw() {
 PrintWriter output = createWriter("pi_test.txt");
 BigDecimal sequence = new BigDecimal(1);
 BigDecimal two = new BigDecimal(2);
 BigDecimal maxVal = new BigDecimal("3000000000");
 sequence = sequence.divide(new BigDecimal(3), 50, sequence.ROUND_HALF_UP);
 sequence = sequence.ONE.subtract(sequence);
 boolean addsub = true; //true is +. false is -.
 BigDecimal divisor = new BigDecimal(3);
 while(divisor.compareTo(maxVal) == -1) {
 divisor = divisor.add(two);
 if(addsub == true) {
 sequence = sequence.add(sequence.ONE.divide(divisor, 50, sequence.ROUND_HALF_UP));
 }
 if(addsub == false) {
 sequence = sequence.subtract(sequence.ONE.divide(divisor, 50, sequence.ROUND_HALF_UP));
 }
 if(addsub==true) addsub=false;
 else addsub=true;
 }
 sequence = sequence.multiply(new BigDecimal(4));
 output.print(sequence.toPlainString());
 output.flush();
 output.close();
 print("\nCalculation Finished!");
 exit();
}

[[[End Code]]]

This iterates through the algorithm almost 3 billion times. Yet it only gives you 10 decimal places of pi. It also takes 5-10 minutes to calculate, depending on the computer. As you add more iterations, it affects the answer less and less. In other words, once you get up into the billions of iterations, it takes many orders of magnitude more of iterations than when you are in the thousands to get more digits. For example, if you replace the 3 billion with ten thousand, you get 3 decimals of accuracy. When you up it to 1 million, you only get 2 more decimal places!

This makes this way of calculating pi good for systems that can only add, subtract, and divide. But modern computers can do a lot more than that. This leads us to the next best algorithm.

Another formula that can be used is this: pi = 16(1/5 – 1/3(1/5)^3 + 1/5(1/5)^5 – 1/7(1/5)^7 + …) – 4(1/239 – 1/3(1/239)^3 + 1/5(1/239)^5 – 1/7(1/239)^7 + …)

This formula leads to pi a lot faster than the other formula. You can put this formula as is into a calculator and it will give you pi to a few decimal places.

This formula is also a loootttt more cpu intensive! After all, it has to multiply some really long decimals to themselves 10000 times (or however many iterations you chose to run it through). The code is very similar to the first formula. It takes only 100 iterations to get 2 digits (one decimal place). My code doesn’t seem to be working for this though, because when I set it to 1000 iterations, it gave me the same number that I got when I did 100 iterations. Not sure what the problem is here, but heres the code anyway:

[[[Start Code]]]

import java.math.*;
void setup() {
 print("Welcome to the Pi calculator. The program will quit when the calculation is finished.");
}
void draw() {
 PrintWriter output = createWriter("pi_test_v2.txt");

 BigDecimal sequenceone = new BigDecimal(1);
 BigDecimal sequencetwo = new BigDecimal(1);

 BigDecimal two = new BigDecimal(2);
 BigDecimal afifth = new BigDecimal("0.2");
 BigDecimal ttnth = sequenceone.divide(sequenceone.valueOf(239), 500, sequenceone.ROUND_HALF_UP);

 BigDecimal maxVal = new BigDecimal("1000"); //cannot be more than the max int value!

 sequenceone = sequenceone.divide(new BigDecimal(5), 1, sequenceone.ROUND_HALF_UP);

 boolean addsub = false; //true is +. false is -.
 BigDecimal divisor = new BigDecimal(1);
 //first loop
 while(divisor.compareTo(maxVal) == -1) {
 divisor = divisor.add(two);
 if(addsub == true) {
 sequenceone = sequenceone.add((sequenceone.ONE.divide(divisor, 50, sequenceone.ROUND_HALF_UP).multiply(afifth)).pow(divisor.intValue()));
 }
 if(addsub == false) {
 sequenceone = sequenceone.subtract((sequenceone.ONE.divide(divisor, 50, sequenceone.ROUND_HALF_UP).multiply(afifth)).pow(divisor.intValue()));
 }
 if(addsub==true) addsub=false;
 else addsub=true;
 }
 //second loop
 addsub = false;
 sequencetwo = ttnth;
 divisor = new BigDecimal(1);
 while(divisor.compareTo(maxVal) == -1) {
 divisor = divisor.add(two);
 if(addsub == true) {
 sequencetwo = sequencetwo.add((sequencetwo.ONE.divide(divisor, 50, sequencetwo.ROUND_HALF_UP).multiply(ttnth)).pow(divisor.intValue()));
 }
 if(addsub == false) {
 sequencetwo = sequencetwo.subtract((sequencetwo.ONE.divide(divisor, 50, sequencetwo.ROUND_HALF_UP).multiply(ttnth)).pow(divisor.intValue()));
 }
 if(addsub==true) addsub=false;
 else addsub=true;
 }

 sequenceone = sequenceone.multiply(sequenceone.valueOf(16));
 sequencetwo = sequencetwo.multiply(sequencetwo.valueOf(4));
 sequenceone = sequenceone.subtract(sequencetwo);
 output.print(sequenceone.toPlainString());
 output.flush();
 output.close();
 print("\nCalculation Finished!");
 exit();
}

[[[End Code]]]

If anyone has any ideas of what causes this code to not work then give me a holler. I hope this blog post served to be interesting to some people. Hopefully it didn’t fry any brains too much…

Advertisements

Memory Junk

When developing on the iPhone, I find that memory management is a real pain. The thing that I found out today that I think is craziest (at least so far) is the fact that Apple includes a special method that is called when the device is low on RAM.

I found out today that this is slightly flawed because when debugging a program that had received the EXC_BAD_ACCESS signal, I found that this method was being called more than once! This is a big problem because if you are deallocating a whole bunch of stuff in that method and it is being called multiple times, your program will crash because it is trying to deallocate something that is already deallocated! It took me hours to figure out what was going wrong and why it was crashing.

Oh well. On to debugging my next program that crashes for no reason.