Calculating PI in java with loops
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 29

Thread: Calculating PI in java with loops

  1. #1
    Join Date
    Sep 2008
    Posts
    2

    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 4-5: 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!

  2. #2
    Join Date
    Jun 1999
    Location
    Eastern Florida
    Posts
    3,741

    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

  3. #3
    Join Date
    Nov 2003
    Posts
    1,405

    Re: Calculating PI in java with loops

    Quote 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 input-1). 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.

  4. #4
    Join Date
    Sep 2008
    Posts
    2

    Re: Calculating PI in java with loops

    Quote Originally Posted by _uj
    Say you're in iteration i (the iterations are counted from 0 up to input-1). 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.

  5. #5
    Join Date
    Nov 2003
    Posts
    1,405

    Re: Calculating PI in java with loops

    Quote 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.

  6. #6
    Join Date
    Jun 1999
    Location
    Eastern Florida
    Posts
    3,741

    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

  7. #7
    Join Date
    Feb 2008
    Posts
    966

    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.

  8. #8
    Join Date
    Jun 1999
    Location
    Eastern Florida
    Posts
    3,741

    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

  9. #9
    Join Date
    Nov 2003
    Posts
    1,405

    Re: Calculating PI in java with loops

    Quote 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.

  10. #10
    Join Date
    Feb 2008
    Posts
    966

    Re: Calculating PI in java with loops

    Quote 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

  11. #11
    Join Date
    Jun 1999
    Location
    Eastern Florida
    Posts
    3,741

    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

  12. #12
    Join Date
    Nov 2003
    Posts
    1,405

    Re: Calculating PI in java with loops

    Quote 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 one-liner doesn't always translate to fast. Even a newbie knows that.

  13. #13
    Join Date
    Feb 2008
    Posts
    966

    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...

  14. #14
    Join Date
    Jun 1999
    Location
    Eastern Florida
    Posts
    3,741

    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

  15. #15
    Join Date
    Nov 2003
    Posts
    1,405

    Re: Calculating PI in java with loops

    Quote 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.

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This a Codeguru.com survey!


On-Demand Webinars (sponsored)