
September 27th, 2008, 03:53 PM
#1
Calculating PI in java with loops
Hello all,
I'm a first year Java student and
I need some help on a practice problem.
Code:
Project 45: THe German mathematician Gottfried Leibniz developed the
following method to approximate the value of PI:
PI/4 = 1  1/3 + 1/5  1/7 + ...
Write a program that allows the user to specify the number of iterations used in this approximation and displays the resulting value.
We need to solve this with either
"for" or "while" loops
Here is what i've got so far:
Code:
import java.util.Scanner;
public class Proj45
{
public static void main(String[]args)
{
Scanner Reader = new Scanner(System.in);
double input = 1;
double output = 1;
System.out.print("Enter the number of iterations:");
input = Reader.nextInt();
for(int x=1 ; x <= input ; x=x+2)
output = ((output)  ((1.0)/(x+2)));
System.out.println(output);
}
}
I don't know how to wrap my head around this.
If any one can help me it would be greatly appreciated.
THanks!

September 27th, 2008, 04:52 PM
#2
Re: Calculating PI in java with loops
Rewrite the equation as:
y/x + y/(x+2) + y/(x+4) + y/(x+6) ...
And alternate the value of y from +1 to 1
Norm

September 28th, 2008, 02:43 AM
#3
Re: Calculating PI in java with loops
Originally Posted by webyugioh
Hello all,
for(int x=1 ; x <= input ; x=x+2)
output = ((output)  ((1.0)/(x+2)));
Say you're in iteration i (the iterations are counted from 0 up to input1). The contribution to the output in that iteration is 1/(2*i+1). In an iteration the contribution is either positive or negative depending on whether i is even or odd. You get this,
Code:
int input = ........;
double output = 0.0;
boolean positive = true;
for (int i=0; i<input; i++) {
double contribution = 1.0/(2.0*((double)i) + 1.0);
if (positive)
output += contribution
else
output = contribution;
positive = !positive;
}
System.out.println("Pi is ", output*4.0);
As an alternative you can decide whether the contribution is positive or negative by checking whether i is even or odd repectively. This approach would then utilize the fact that (i%2==0) evaluates to true when i is even and to false when i is odd.
Note that in the contribution calculation care has been taken to use double throughout. This is to avoid implicit conversion surprises. Double literals have been used (1.0 instead of 1 etcetera) and the int i has been explicitly cast to double.
Last edited by _uj; September 28th, 2008 at 03:36 AM.

September 28th, 2008, 01:15 PM
#4
Re: Calculating PI in java with loops
Originally Posted by _uj
Say you're in iteration i (the iterations are counted from 0 up to input1). The contribution to the output in that iteration is 1/(2*i+1). In an iteration the contribution is either positive or negative depending on whether i is even or odd. You get this,
Code:
int input = ........;
double output = 0.0;
boolean positive = true;
for (int i=0; i<input; i++) {
double contribution = 1.0/(2.0*((double)i) + 1.0);
if (positive)
output += contribution
else
output = contribution;
positive = !positive;
}
System.out.println("Pi is ", output*4.0);
As an alternative you can decide whether the contribution is positive or negative by checking whether i is even or odd repectively. This approach would then utilize the fact that (i%2==0) evaluates to true when i is even and to false when i is odd.
Note that in the contribution calculation care has been taken to use double throughout. This is to avoid implicit conversion surprises. Double literals have been used (1.0 instead of 1 etcetera) and the int i has been explicitly cast to double.
I thank you very much, it works perfectly.
If you don't mind, can you explain some things to me.
I am only a few weeks into programming so I do not understand everything you have there.
Here is the program that works perfectly:
Code:
import java.util.Scanner;
public class cheat
{
public static void main(String[]args)
{
Scanner Reader = new Scanner(System.in);
int input;
System.out.print("Enter the number of iterations:");
input = Reader.nextInt(); // set input as the input
double output = 0.0;
boolean positive = true; // don't know this
for (int i=0; i<input; i++) {
double sum = 1.0/(2.0*((double)i) + 1.0); //how no idea how this works
if (positive)
output += sum; //same as output = output + sum
else
output = sum; // same as output = output = output  sum
positive = !positive; // Don't know this
}
System.out.println("Pi/4 is " + output);
}
}
what is "boolean positive = true" do?
what does that ((double)i) do?
how does if (positive) work?
what does positive = !positive do?
I thank you very much for your help, but it seems that you are way above my head.
EDIT: I found out another way to do it from another form:
Code:
import java.util.Scanner; // import scanner util
public class Proj45v2 // name the project
{
public static void main(String[]args)
{
Scanner Reader = new Scanner(System.in); // set up the scanner variable
int input; // this is initialized and given value by the user
System.out.print("Enter the number of iterations:");
input = Reader.nextInt(); //sets user input
double sum = 0; //sets up the sum variable
for (int i = 1; i <= input; i++) {
//i starts as the int 1 ; as long as less than or equal the input ; i = i+1 after each loop
double numToAdd = (1.0 / ((i * 2)  1));
// put ((i * 2)  1)) on botom so that
// *2 to makes it even and 1 to make it odd
if (i%2 > 0) // if the remander of i/2 is >0 then add the
// preivous number to the new one
sum = sum + numToAdd;
else // if the remander of i/2 is not >0 then subtract the
// previous number to the new one
sum = sum  numToAdd;
System.out.println("PI/4 is equal to " + sum);
// outputs the answer
}
}
}
Last edited by webyugioh; September 28th, 2008 at 02:56 PM.

September 28th, 2008, 03:36 PM
#5
Re: Calculating PI in java with loops
Originally Posted by webyugioh
I thank you very much for your help, but it seems that you are way above my head.
It's very basic Java usage.
what is "boolean positive = true" do?
how does if (positive) work?
what does positive = !positive do?
Check out the boolean primitive.
what does that ((double)i) do?
It converts an int into a double. It's called a cast.

September 29th, 2008, 06:53 AM
#6
Re: Calculating PI in java with loops
Here's another, slightly shorter way to do it:
Code:
public class ComputePI {
public static void main(String[] args) {
double pi = 0;
double y = 1;
int lps = 90000000*2;
int cnt = 0;
for(int x=1; x < lps; x+=2) {
// System.out.println("x=" + x + ", y=" + y + " y/x=" + (y/x) + ", pi=" + pi);
pi = pi + (y/x);
y = y; // alternate the sign each time
cnt++;
}
System.out.println("PI=" + 4*pi + " after " + cnt); //PI=3.141592642478473 after 90000000
}
}
Norm

September 30th, 2008, 08:35 AM
#7
Re: Calculating PI in java with loops
There is a MUCH better way to alternate signs for Taylor series. All you simply need to do is raise 1 to the Ith power:
Math.pow(1,i)
double sum = 1.0;
for(int i = 1; i < input; ++i)
sum += Math.pow(1,i)*1.0/(2.0*((double)i) + 1.0);
And use that in the actual equation. Inside of the loop should be one line of code.

September 30th, 2008, 10:02 AM
#8
Re: Calculating PI in java with loops
What do you think the cost of Math.pow() is vs y = y?
I'd code an extra line of code for the expense.
Norm

September 30th, 2008, 10:47 AM
#9
Re: Calculating PI in java with loops
Originally Posted by Norm
What do you think the cost of Math.pow() is vs y = y?
I'd code an extra line of code for the expense.
I agree. Using Math.pow like that is something only a newbie would do.
If speed is important I have a suggestion to your solution,
Code:
double pi=0;
for(int x=1; x < lps; x+=4) pi += 1.0/(double)x;
for(int x=3; x < lps; x+=4) pi = 1.0/(double)x;
You first add up all positive contributions in one loop, then you subtract all negative contributions in another. The total number of iterations is the same as before but there's no need anymore to keep track of an alternating sign while looping.
Last edited by _uj; September 30th, 2008 at 10:58 AM.

October 1st, 2008, 08:07 AM
#10
Re: Calculating PI in java with loops
Originally Posted by _uj
I agree. Using Math.pow like that is something only a newbie would do.
_uj, you're an ***, no wonder you and dlorde are always butting heads. Lets look at YOUR "noob" solution:
Code:
int input = ........;
double output = 0.0;
boolean positive = true;
for (int i=0; i<input; i++) {
double contribution = 1.0/(2.0*((double)i) + 1.0);
if (positive)
output += contribution
else
output = contribution;
positive = !positive;
}
Oh yes, having if else statements in a foor loop checking a boolean value is MUCH more elegant right?
You want a solution that is not expensive? Sorry I didn't know that speed was such an issue here...
Code:
double sum = 1.0;
for(int i = 1; i < input; ++i)
sum += Math.pow(1,i%2)*1.0/(2.0*((double)i) + 1.0);
There, its not expensive anymore since it is either doing 1 no times (to the 0th power) or only once. WAY more elegant than yours and just as effective. Go ahead noob, benchmark it

October 1st, 2008, 09:03 AM
#11
Re: Calculating PI in java with loops
I was curious so I added the Math.pow() to the loop. It took 10 times as long. Elegant is nice in art galleries and fashion shows. Efficient wins for me every time in programs.
Code:
public class ComputePI {
public static void main(String[] args) {
double pi = 0;
double y = 1;
final int lps = 90000000*2; // this as double increases time to 1,123,755,952 ???
int cnt = 0;
long start = System.nanoTime();
for(int x=1; x < lps; x+=2) {
// System.out.println("x=" + x + ", y=" + y + " y/x=" + (y/x) + ", pi=" + pi);
pi = pi + (y/x);
y = y;
// Math.pow(1,x); //dur=11,930,493,680 <<< MUCH LONGER!!! 10X
cnt++;
} // end for(x)
System.out.println("PI=" + 4*pi + " after " + cnt //PI=3.141592642478473 after 90000000
+ " dur=" + (System.nanoTime()  start));
//(double x)dur=1317885653,=1052510305
//(double lps)=1112621297 <<<< LONGER???
//(int x) dur=1068757621,=1,058,560,794,=1,066,056,440
}
}
Norm

October 1st, 2008, 10:09 AM
#12
Re: Calculating PI in java with loops
Originally Posted by ProgramThis
Lets look at YOUR "noob" solution:
My solution in #3 was aimed at a newbie and it came with a thorough explanation. The aim was to be straightforward, not elegant or effective.
If you want a both elegant and effective solution have a look at my suggested modification in #9 of Norm's solution. It should be the fastest solution so far whereas your Math.pow based solution is the slowest. A oneliner doesn't always translate to fast. Even a newbie knows that.

October 1st, 2008, 11:17 AM
#13
Re: Calculating PI in java with loops
Norm, try the version that I posted last with i (x in your case) %2, it is much faster. The difference at 1,000,000 iterations is ~70 ms... If you are worried about 70 milliseconds then... well go with another solution. For 99% of anything you are going to need this for a 70 ms slowdown is nothing.
For both you and uj about speed: not everything in programming is about speed. Why do you think people still use things like bubble or merge sorts. Because they are quick and easy to implement if speed is not critical, which in most cases will only be milliseconds slower. Not everything you do has to be the fastest computational wise out there. Some people prefer readability to speed when the difference is a few milliseconds. Even newbies know that uj...

October 1st, 2008, 12:12 PM
#14
Re: Calculating PI in java with loops
Ok how about easy to understand code?
Which is easier to understand:
y = y; // change sign
Math.pow(1,i%2) // what does this do?
Norm

October 1st, 2008, 01:29 PM
#15
Re: Calculating PI in java with loops
Originally Posted by ProgramThis
Norm, try the version that I posted last with i (x in your case) %2, it is much faster. The difference at 1,000,000 iterations is ~70 ms... If you are worried about 70 milliseconds then... well go with another solution. For 99% of anything you are going to need this for a 70 ms slowdown is nothing.
Using Math.pow(1,i%2) will never be an elegant nor an efficient way of establishing whether i is even or odd and evaluate to 1 or 1 accordingly.
And to not make it ridicously slow you had to "adapt" one of the parameters (the i%2), in order to induce Math.pow to use two special cases which can be performed faster than the general case, making the purpose of the call even more obscure.
The significance of 70 ms is in the eye of the beholder. It could be nothing and it could be ages. What's interesting is how much slower it is than the alternative. 10 times? 100 times? 1000 times? When that has been established a user is free to use whichever alternative best fits the bill.
Last edited by _uj; October 1st, 2008 at 01:35 PM.
Posting Permissions
 You may not post new threads
 You may not post replies
 You may not post attachments
 You may not edit your posts

Forum Rules

Click Here to Expand Forum to Full Width
This a Codeguru.com survey!
OnDemand Webinars (sponsored)
