简体   繁体   中英

Calculate PI using Random Numbers

Having trouble with the following question:

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 Random module has several random number generating functions that can be used. For example, the function uniform(a, b) returns a floating point random number in the range a (inclusive) and b (exclusive).

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. The way we achieve that is:

xPos = random.uniform (-1.0, 1.0)
yPos = random.uniform (-1.0, 1.0)

To determine if a point is inside the circle its distance from the center of the circle must be strictly less than the radius of the circle. The distance of a point with coordinates ( xPos, yPos ) from the center is math.hypot (xPos, yPos). The radius of the circle is 1 unit.

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

import math
import random

def computePI ( numThrows ):
  ... 

def main ():
  ...

main()

Your function main() will call the function computePI() for a given number of throws. The function computePI() will simulate the throw of a dart by generating random numbers for the x and y coordinates. You will determine if that randomly generated point is inside the circle or not. You will do this as many times as specified by the number of throws. You will keep a count of the number of times a dart lands within the circle. That count divided by the total number of throws is the ratio π/4. The function computePI() will then return the computed value of PI. In your function 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, 100,000, 1,000,000, and 10,000,000. You will call the function computePI() with these numbers as input parameters. Your output will be similar to the following, ie the actual values of your Calculated PI and Difference will be different but close to the ones shown:

Computation of PI using Random Numbers 

num = 100        Calculated PI = 3.320000   Difference = +0.178407 
num = 1000       Calculated PI = 3.080000   Difference = -0.061593 
num = 10000      Calculated PI = 3.120400   Difference = -0.021193 
num = 100000     Calculated PI = 3.144720   Difference = +0.003127 
num = 1000000    Calculated PI = 3.142588   Difference = +0.000995 
num = 10000000   Calculated PI = 3.141796   Difference = +0.000204 

Difference = Calculated PI - math.pi

Your output must be in the above format. The number of throws must be left justified. The calculated value of π and the difference must be expressed correct to six places of decimal. There should be plus or minus sign on the difference. Read the relevant sections in the book on formatting.

Till now I have done:

import math
import random


def computePI (numThrows):

  xPos = random.uniform (-1.0, 1.0)
  yPos = random.uniform (-1.0, 1.0)

  in_circle = 0
  throws = 0

  while (throws < numThrows):
    if math.hypot (xPos, yPos) <= 1:
      in_circle += 1
    throws += 1
  pi = (4 * in_circle) / numThrows
  return pi


def main ():

  throws = (100, 1000, 10000, 100000, 1000000, 10000000)
  for numThrows in throws[0:7]:

main ()

I am having trouble calling the ComputePI function in the Main function. Also how do I print num with left indentation and ensure that all numbers have the required decimal space? Thank you!

Your program has three main issues:

  1. Generating random numbers in the wrong place

    xPos = random.uniform (-1.0, 1.0) yPos = random.uniform (-1.0, 1.0)

    These lines are executed only once when you enter the computePI() function. You then proceed to calculate the exact same value of hypot for hundreds or even thousands of iterations. Put these lines inside the while loop.

  2. Integer arithmetic

    pi = (4 * in_circle) / numThrows

    Since in_circle and numThrows are both integers, this calculation will be performed using integer arithmetic (in Python 2, at least). Changing the constant from 4 to 4.0 will change this to a floating point calculation:

     pi = (4.0 * in_circle) / numThrows
  3. Incomplete main() function:

    There's no need to use a subset of your throws tuple, and you haven't added a body to your for loop. Try this:

     for numThrows in (100, 1000, 10000, 100000, 1000000, 10000000): randpi = computePI(numThrows) diff = randpi - math.pi print "num = %-8d Calculated PI = %8.6f Difference = %+9.6f" % \\ (numThrows, randpi, diff)

This is how I find it easy.

import random
import math
def approximate_pi():
    total_points = 0
    within_circle = 0
    for i in range (10000):
        x = random.random()
        y = random.random()
        total_points += 1
        distance = math.sqrt(x**2+y**2)
        if distance < 1:
            within_circle += 1
        if total_points % 1000 == 0:
            pi_estimate = 4 * within_circle / total_points
            yield pi_estimate

set total point generated and points withing the circle to zero

total_points = 0
within_circle = 0

generate the random values of x and y for multiple times. Calculate the distance of the point from the center of the circle or (0,0). Then if the distance is less than one it means that it's within the circle so it is incremented.

distance = math.sqrt(x**2+y**2)
        if distance < 1:
            within_circle += 1

Now if you have generated let's say multiple of 1000(1000 because we have taken the range for 10,000 so 1000 to get 10 values of pi), calculate the estimated value of pi using this formula which you know already.and the tied the estimate value(pi_estmate)

if total_points % 1000 == 0:
            pi_estimate = 4 * within_circle / total_points
            yield pi_estimate
pi_estimates = list(es for es in approximate_pi())
errors = list(estimate-math.pi for estimate in approximate_pi())
print(pi_estimates)
print(errors)

OUTPUT:

Estimates

[3.096, 3.142, 3.1253333333333333, 3.121, 3.1384, 3.136, 3.1314285714285712, 3.133, 3.1342222222222222]

Errors

[0.04240734641020705, 0.02240734641020703, 0.03307401307687341, 0.020407346410206806, 0.02320734641020694, 0.0017406797435404187, -0.009021225018364554, -0.011592653589793223, -0.016703764700904067]

Hope you understood, I hope my explanation was easy to understand, I am a beginner and learning stuff if there is anything wrong please feel free to notify. Thank you

Essentially what the statement you've written above says:


import math

def find_pi(iterations):
  return sum(
    1 for _ in range(iterations) if math.hypot(
                          random.random(), random.random()) <= 1) * 4.0/iterations

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM