Calculate PI using Random Numbers

having big problems with my code!

Page 1 of 1

2 Replies - 41767 Views - Last Post: 11 July 2007 - 02:32 PM Rate Topic: -----

#1 KoreyAusTex  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 11
  • Joined: 02-July 07

Calculate PI using Random Numbers

Post icon  Posted 10 July 2007 - 05:17 PM

Ok, I am having problems with my code, I am a newbie but I think I am close to the solution. here is the assignment:

In geometry the ratio of the circumference of a circle to its diameter is known as π. The value of π can be estimated from an infinite series of the form:

π / 4 = 1 - (1/3) + (1/5) - (1/7) + (1/9) - (1/11) + ...

There is another novel approach to calculate π. Imagine that you have a dart board that is 2 units square. It inscribes a circle of unit radius. The center of the circle coincides with the center of the square. Now imagine that you throw darts at that dart board randomly. Then the ratio of the number of darts that fall within the circle to the total number of darts thrown is the same as the ratio of the area of the circle to the area of the square dart board. The area of a circle with unit radius is just π square unit. The area of the dart board is 4 square units. The ratio of the area of the circle to the area of the square is π / 4.

To simuluate the throwing of darts we will use a random number generator. The Math class has a random() method that can be used. This method returns random numbers between 0.0 (inclusive) to 1.0 (exclusive). There is an even better random number generator that is provided the Random class. We will first create a Random object called randomGen. This random number generator needs a seed to get started. We will read the time from the System clock and use that as our seed.

Random randomGen = new Random ( System.currentTimeMillis() );
Imagine that the square dart board has a coordinate system attached to it. The upper right corner has coordinates ( 1.0, 1.0) and the lower left corner has coordinates ( -1.0, -1.0 ). It has sides that are 2 units long and its center (as well as the center of the inscribed circle) is at the origin.

A random point inside the dart board can be specified by its x and y coordinates. These values are generated using the random number generator. There is a method nextDouble() that will return a double between 0.0 (inclusive) and 1.0 (exclusive). But we need random numbers between -1.0 and +1.0. The way we achieve that is:

double xPos = (randomGen.nextDouble()) * 2 - 1.0;
double yPos = (randomGen.nextDouble()) * 2 - 1.0;
To determine if a point is inside the circle its distance from the center of the circle must be less than the radius of the circle. The distance of a point with coordinates ( xPos, yPos ) from the center is Math.sqrt ( xPos * xPos + yPos * yPos ). The radius of the circle is 1 unit.

The class that you will be writing will be called CalculatePI. It will have the following structure:

import java.util.*;

public class CalculatePI
{
public static boolean isInside ( double xPos, double yPos )
{ ... }

public static double computePI ( int numThrows )
{ ... }

public static void main ( String[] args )
{ ... }
}
In your method main() you want to experiment and see if the accuracy of PI increases with the number of throws on the dartboard. You will compare your result with the value given by Math.PI. The quantity Difference in the output is your calculated value of PI minus Math.PI. Use the following number of throws to run your experiment - 100, 1000, 10,000, and 100,000. You will call the method computePI() with these numbers as input parameters. Your output will be of the following form:

Computation of PI using Random Numbers

Number of throws = 100, Computed PI = ..., Difference = ...
Number of throws = 1000, Computed PI = ..., Difference = ...
Number of throws = 10000, Computed PI = ..., Difference = ...
Number of throws = 100000, Computed PI = ..., Difference = ...

* Difference = Computed PI - Math.PI

In the method computePI() you will simulate the throw of a dart by generating random numbers for the x and y coordinates. You will call the method isInside() to determine if the point is inside the circle or not. This you will do as many times as specified by the number of throws. You will keep a count of the number of times a dart landed inside the circle. That figure divided by the total number of throws is the ratio π / 4. The method computePI() will return the computed value of PI.

Here is what I have done so far but the value of PI is coming out 0.0 and the difference is coming out the negative value of PI (-3.141592....) I having been debugging for the last day and a half. I've kinda have lost the ability to be objective about this and was wondering what anyone though about what I might be doing wrong?


import java.util.*;

public class CalculatePI2
{  
	public static boolean isInside (double xPos, double yPos)	
	{   
		boolean result;   
		double distance = Math.sqrt((xPos * xPos) + (yPos * yPos)); 
		if (distance < 1)
			result = false; 
			return(distance < 1); 
	}
	
	public static double computePI (int numThrows)
	{  
		Random randomGen = new Random (System.currentTimeMillis());		
		int hits = 0;
		double PI = 0;		 
		
		for (int i = 0; i <= numThrows; i++)
		{   
			double xPos = (randomGen.nextDouble()) * 2 - 1.0;
			double yPos = (randomGen.nextDouble()) * 2 - 1.0;
			if (isInside(xPos, yPos)) 
			{
				hits++;
			}
			PI = (4 * (hits/numThrows));
		}
		return PI; 
	}
 
	public static void main (String[] args)
	{ 
		Scanner reader = new Scanner (System.in);
		System.out.println("This program approximates PI using the Monte Carlo method.");
		System.out.println("It simulates throwing darts at a dartboard.");
		System.out.print("Please enter number of throws: ");
		int numThrows = reader.nextInt();
		double PI = computePI(numThrows);
		double Difference = PI - Math.PI;
		System.out.println ("Number of throws = " + numThrows + ", Computed PI = " + PI + ", Difference = " + Difference );		
	}
}



I actually made the program to where the user could enter the number of throws and I really only needed to have the program approximate Pi for the values of 100, 1000, 10000, and 100000. Not sure if he is going to like that.

This post has been edited by KoreyAusTex: 10 July 2007 - 05:20 PM


Is This A Good Question/Topic? 0
  • +

Replies To: Calculate PI using Random Numbers

#2 OuFeRRaT  Icon User is offline

  • New D.I.C Head

Reputation: 1
  • View blog
  • Posts: 6
  • Joined: 15-June 07

Re: Calculate PI using Random Numbers

Posted 11 July 2007 - 01:02 PM

http://java.sun.com/...ml#nextDouble()

nextDouble() returns a random double between 0 an 1, so your isInside function never returns true.

;)
Was This Post Helpful? 0
  • +
  • -

#4 Martyr2  Icon User is online

  • Programming Theoretician
  • member icon

Reputation: 4444
  • View blog
  • Posts: 12,318
  • Joined: 18-April 07

Re: Calculate PI using Random Numbers

Posted 11 July 2007 - 02:32 PM

Hello KoreyAusTex,

Well you were close and I didn't actually have to modify too much to make it work. Before I get to the solution I wanted to make a small comment about what OuFeRRaT had said... nextDouble does return between 0 and 1, but that is why you put it in the expression (randomGen.nextDouble()) * 2 - 1.0 to give you those numbers between -1 and 1. So that is certainly right how you are doing it.

Some notes about your code I wanted to comment on....

1) Your isInside function doesn't need the if statement there, it is not doing anything besides setting result = false and for that matter you don't even need the result variable. You return a boolean with the comparison in your return statement anyways.

2) Where you calculate and set PI is inside your for loop. I recommend you take that out and do your calculate after the loop is completed and you have a total number of hits to divide by your throws. This will save you some processing time because you won't need to do the calculation each time through the loop.

3) Your for loop was actually off by one... you start at zero and go to less than or EQUAL too which would give you one more throw than you typed. If I entered 5, the for loop would go 6 times.

4) Last but not least, your data type conversions. You take in an integer for the number of throws, but then use it with division that may give you unexpected results. This is "integer division" and it can be crazy. 4/3 doesn't give you a decimal, it will give you 1. Because of this, you should use doubles when you are attempting to capture a value which may end up as a decimal. So to fix this, you would convert numThrows to a double then use it in your calculations. You will also want to change 4 to 4.0 just to make sure everything jives. The hits variable will convert to double since you are using a double to divide by, but you could certainly change that to a double just before the calculation if you like.

After these minor changes this is the code I get and have tested. It is coming out quite accurate to PI as you can guess. I have put some trial results at the end so you can make sure it is doing what you exactly wanted it to do...

import java.util.*;

public class CalculatePI2
{  
	public static boolean isInside (double xPos, double yPos)	
	{	
		double distance = Math.sqrt((xPos * xPos) + (yPos * yPos));

		return (distance < 1.0);
	}
	
	public static double computePI (int numThrows)
	{  
		Random randomGen = new Random (System.currentTimeMillis());		
		int hits = 0;
		double PI = 0;		
		
		for (int i = 1; i <= numThrows; i++)
		{  
			double xPos = (randomGen.nextDouble()) * 2 - 1.0;
			double yPos = (randomGen.nextDouble()) * 2 - 1.0;
			if (isInside(xPos, yPos))
			{
				hits++;
			}
		}

	double dthrows = numThrows;

	PI = (4.0 * (hits/dthrows));

		return PI;
	}

	public static void main (String[] args)
	{
		Scanner reader = new Scanner (System.in);
		System.out.println("This program approximates PI using the Monte Carlo method.");
		System.out.println("It simulates throwing darts at a dartboard.");
		System.out.print("Please enter number of throws: ");
		int numThrows = reader.nextInt();
		double PI = computePI(numThrows);
		double Difference = PI - Math.PI;
		System.out.println ("Number of throws = " + numThrows + ", Computed PI = " + PI + ", Difference = " + Difference );		
	}
}



Trial data....

Throws: 100 - Computed PI: 2.88 - Difference: -0.261592...
Throws: 5 - Computed: 3.2 - Difference: 0.058407....
Throws: 10,000 - Computed: 3.1344 - Difference: -0.0071926...

Enjoy!
Was This Post Helpful? 1

Page 1 of 1