繁体   English   中英

使用随机数计算 PI

[英]Calculate PI using Random Numbers

遇到以下问题:

在几何学中,圆的周长与其直径之比称为 π。 可以从以下形式的无限级数估计 π 的值:

π / 4 = 1 - (1/3) + (1/5) - (1/7) + (1/9) - (1/11) + ... 还有另一种计算 π 的新方法。 想象一下,您有一个 2 个单位平方的飞镖板。 它内接一个单位半径的圆。 圆的中心与正方形的中心重合。 现在想象一下你随机向飞镖板扔飞镖。 那么落入圆内的飞镖数与投出的飞镖总数的比值等于圆的面积与方形飞镖板面积的比值。 单位半径的圆的面积就是π平方单位。 飞镖盘的面积为4平方单位。 圆的面积与正方形的面积之比为π/4。

为了模拟飞镖的投掷,我们将使用随机数生成器。 Random 模块有几个可以使用的随机数生成函数。 例如,函数uniform(a, b) 返回a(包含)和b(不包含)范围内的浮点随机数。

想象一下,方形飞镖板附有一个坐标系。 右上角有坐标 (1.0, 1.0),左下角有坐标 (-1.0, -1.0)。 它的边长为 2 个单位,其中心(以及内切圆的中心)位于原点。

飞镖盘内的随机点可以通过其 x 和 y 坐标指定。 这些值是使用随机数生成器生成的。 我们实现这一目标的方式是:

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

要确定一个点是否在圆内,它到圆心的距离必须严格小于圆的半径。 坐标为 ( xPos, yPos ) 的点到中心的距离为 math.hypot (xPos, yPos)。 圆的半径为 1 个单位。

您将要编写的程序将称为CalculatePI。 它将具有以下结构:

import math
import random

def computePI ( numThrows ):
  ... 

def main ():
  ...

main()

您的函数 main() 将针对给定的抛出次数调用函数 computePI()。 函数computePI() 将通过为x 和y 坐标生成随机数来模拟飞镖的投掷。 您将确定该随机生成的点是否在圆内。 您将按照抛出次数指定的次数执行此操作。 您将计算飞镖落在圆圈内的次数。 该计数除以总投掷次数是比率 π/4。 然后,函数computePI() 将返回PI 的计算值。 在您的函数 main() 中,您想进行实验,看看 PI 的准确性是否随着飞镖投掷次数的增加而增加。 您将结果与 math.pi 给出的值进行比较。 输出中的数量差异是您计算出的 PI 值减去 math.pi。 使用以下投掷次数来运行您的实验 - 100、1000、10,000、100,000、1,000,000 和 10,000,000。 您将使用这些数字作为输入参数调用函数 computePI()。 您的输出将类似于以下内容,即您的计算 PI 和差异的实际值将有所不同,但接近于显示的值:

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

您的输出必须采用上述格式。 投掷次数必须左对齐。 π 的计算值和差值必须准确表示到小数点后六位。 差异上应该有加号或减号。 阅读本书中有关格式化的相关章节。

到目前为止,我已经完成了:

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 ()

我在调用 Main 函数中的 ComputePI 函数时遇到问题。 另外,如何使用左缩进打印 num 并确保所有数字都具有所需的小数位? 谢谢!

你的程序有三个主要问题:

  1. 在错误的地方生成随机数

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

    这些行仅在您输入computePI()函数时执行一次。 这样就可以进行计算的值完全相同hypot数百甚至数千的迭代。 将这些行放在while 循环中。

  2. 整数运算

    pi = (4 * in_circle) / numThrows

    由于in_circlenumThrows都是整数,因此将使用整数算法(至少在 Python 2 中)执行此计算。 将常量从4更改为4.0会将其更改为浮点计算:

     pi = (4.0 * in_circle) / numThrows
  3. 不完整的main()函数:

    不需要使用throws元组的子集,并且您还没有在for循环中添加主体。 试试这个:

     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)

这就是我觉得很容易的方式。

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

将生成的总点数和圆圈内的点数设置为零

total_points = 0
within_circle = 0

多次生成 x 和 y 的随机值。 计算点到圆心或 (0,0) 的距离。 然后,如果距离小于 1,则表示它在圆内,因此它会增加。

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

现在,如果您生成了 1000 的倍数(1000,因为我们取了 10,000 的范围,所以 1000 来获得 10 个 pi 值),使用您已经知道的这个公式计算 pi 的估计值。并绑定估计值(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)

输出:

估计

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

错误

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

希望你理解,我希望我的解释容易理解,我是初学者,学习的东西,如果有什么不对的,请随时通知。 谢谢

基本上你上面写的声明说的是:


import math

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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