Search code examples
javapi

Estimating pi by throwing darts


Essentially i want to find an estimate of pi by throwing a dart at the unit circle. So I want to throw a dart a the positive x and y quadrant of the unit circle , each dart thrown will give me a random position in the x and y direction that is less that 1. I then need to find the distance from the origin from that point. The approximation of pi will come from when the distance of the dart from the origin is less than 1 when calculated, this will count as a hit, anything else will count as a miss. Using this number pi is found by (#hits/#of tosses)*4 since i will only be looking at 1/4 of the circle .I then want to print a table with different results depending on how many darts are thrown. my code is below, I'm confused on a lot of things, mainly how do I collect all the data and print it all, I was thinking of using an ArrayList of arrays of ints since it will not be limited to the amount of trials I want to do but I am unsure on how to proceed. Any help is useful, thanks!

public static void main(String[]args){
    
    int[] darts_Thrown = {10, 100, 1000, 10000, 100000,1000000};
    

   

  //  for( int i = 0; i < points.length; i++){
   //     System.out.print(points[i]);
  //  }



   for (int i = 0; i < darts_Thrown.length;i++){
        
       for (int j = 0; j < darts_Thrown[i]; j++){
        int test = 0;
        double [] points = getPoint();
       // distanceToOrigin(points[0],points[1]);
       // getHits();
       test++;
       System.out.printf("%d",test);
       }
       System.out.printf("%n%s", "hi ");
   }
   
}
public static double[] getPoint()//code to generate x and y and return them in a double array
{
    
    double[] point_X_Y = {Math.random(),Math.random()};

    return point_X_Y;
    
    
}
public static double distanceToOrigin(double x,double y) //code to compute distance from point (x,y) to origin (0,0)
{
   
    
    double distance = Math.sqrt((Math.pow(x,2))+(Math.pow(y,2))); // used to find distance from origin
   
    return distance;
    
    
}
public static int getHits(int n)
{
    int hits = 0;
    int misses=0;
    
//double distance = distanceToOrigin(points[0], points[1]);
    //if (distance < 0){
  //      hits++;
   //     return hits;
  //  }
  //  else{
   //     misses++;
    //return misses;
  //  }
   // return 0;
    //code to get hits given n= number of darts
}

}


Solution

  • The formula #hits/#tosses is correct in thought, but it's gotta be too small, since it can't possibly be larger than 1. It turns out that that formula will approximate the value of PI/4, so the approximation of PI is #hits/#tosses*4.

    For each trial, it isn't really practical to "collect all the data and print it all", if you want to get a reasonable approximation of PI by the end, because it's going to take a million or so trials to get at all close. I found that 1M trials gives a pretty good result, and 10M often gives you the right result to 4 decimal places. There's no use in printing even a few 100 individual trials, much less 1M of them. So I think all you can really print is the trial number, the number of throws, the number of hits, and the final approximation of PI. Here's code that does that:

    public class Test {
    
        public static void main(String[]args){
    
            int[] darts_Thrown = {10, 100, 1000, 10000, 100000, 1000000, 10000000};
    
            for (int i = 0; i < darts_Thrown.length;i++){
    
                int hits = 0;
                for (int j = 0; j < darts_Thrown[i]; j++){
                    double [] points = getPoint();
                    double distance = distanceToOrigin(points[0],points[1]);
                    if (distance <= 1.0)
                        hits++;
                }
                double pi_est = (double)hits / darts_Thrown[i] * 4.0;
    
                System.out.printf("Trial: %d  Throws: %d  Hits: %d  Approximation of PI (hits/throws*4): %.4f\n",
                        i, darts_Thrown[i], hits, pi_est);
            }
    
        }
        public static double[] getPoint()//code to generate x and y and return them in a double array
        {
            final double[] doubles = {Math.random(), Math.random()};
            return doubles;
        }
        public static double distanceToOrigin(double x,double y) //code to compute distance from point (x,y) to origin (0,0)
        {
            double distance = Math.sqrt((Math.pow(x,2))+(Math.pow(y,2))); // used to find distance from origin
            return distance;
        }
    }
    

    Result:

    Trial: 1  Throws: 10  Hits: 8  Approximation of PI (hits/throws*4): 3.2000
    Trial: 2  Throws: 100  Hits: 79  Approximation of PI (hits/throws*4): 3.1600
    Trial: 3  Throws: 1000  Hits: 773  Approximation of PI (hits/throws*4): 3.0920
    Trial: 4  Throws: 10000  Hits: 7800  Approximation of PI (hits/throws*4): 3.1200
    Trial: 5  Throws: 100000  Hits: 78409  Approximation of PI (hits/throws*4): 3.1364
    Trial: 6  Throws: 1000000  Hits: 785250  Approximation of PI (hits/throws*4): 3.1410
    Trial: 7  Throws: 10000000  Hits: 7852455  Approximation of PI (hits/throws*4): 3.1410
    

    The formula is pretty easy to derive. For a circle with radius 1 centered at the origin, 1/4 of it will be in the quadrant x=0-1, y=0-1. The points inside that circle are 1 unit from the origin or closer, so those are all 'hits'. A 1/4 of a circle of radius 1 has an area of PI * r^2 / 4 = PI * 1^2 / 4 = PI/4. The entire target area is x * y = 1 * 1 = 1. So hits/throws = (PI/4)/(1) = PI/4. Multiply both sides by 4 to get PI = hits/throws * 4.