[英]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 并确保所有数字都具有所需的小数位? 谢谢!
你的程序有三个主要问题:
在错误的地方生成随机数
xPos = random.uniform (-1.0, 1.0) yPos = random.uniform (-1.0, 1.0)
这些行仅在您输入computePI()
函数时执行一次。 这样就可以进行计算的值完全相同hypot
数百甚至数千的迭代。 将这些行放在while 循环中。
整数运算
pi = (4 * in_circle) / numThrows
由于in_circle
和numThrows
都是整数,因此将使用整数算法(至少在 Python 2 中)执行此计算。 将常量从4
更改为4.0
会将其更改为浮点计算:
pi = (4.0 * in_circle) / numThrows
不完整的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.