我写了这个方法:
def approx_pi(n, p):
"""
Approximates Pi by putting dots in a square and counting
the dots in the max possible circle in that square.
:param n: Number of dots
:param p: Precision used for urandom
:return: Approximation of Pi
"""
in_circle = 0
k = 100
max_int = (2**(8*p)-1)
for i in range(n):
# get two random Numbers between 0 and 1
x = int.from_bytes(os.urandom(p), byteorder='big')/max_int
y = int.from_bytes(os.urandom(p), byteorder='big')/max_int
if x ** 2 + y ** 2 <= 1:
in_circle += 1
# Just for debugging
if (i+1) % k == 0:
k = int(k*1.01)
print(i, '\t',4*in_circle/i)
sys.stdout.flush()
return 4*in_circle/n
在我的大部分Testruns中,它在3.141稳定,然后在该值附近发散。 这是urandom的弱点吗?但如果是这样,为什么pi不会向一个方向转移?或者我的代码有问题。
答案 0 :(得分:2)
首先。你的代码很混乱。如果您通过名称调用变量,可以更好地了解它们的含义。
我已将代码简化为必要的行。因此,我使用随机库来生成点位置。
这种方法的问题在于收敛速度非常慢。凭借10 ** 8分,我获得了3.14167604。
import random
def approx_pi(points):
"""
Approximates Pi by putting dots in a square and counting
the dots in the max possible circle in that square.
:param points: Number of dots
:return: Approximation of Pi
"""
in_circle = 0
for dummy_i in xrange(points):
# get two random Numbers between 0 and 1
x_dot_position = random.random()
y_dot_position = random.random()
if x_dot_position ** 2 + y_dot_position ** 2 <= 1:
in_circle += 1
return 4.0*in_circle/points
<强>编辑强> 你对函数random.random()很严格。所以在下一个代码中我使用了random.random_integers,它是[low,high]值之间的均匀分布。
代码是并行化的,我尝试获得10 ** 10分:
PI = 3.14157765 Tiempo de calculo = 3790秒
import multiprocessing
import time
import numpy as np
starting_point = time.time()
def approx_pi(point):
"""
Approximates Pi by putting dots in a square and counting
the dots in the max possible circle in that square.
:param points: Number of dots
:return: Approximation of Pi
"""
# get two random Numbers between 0 and 1
x_dot_position = float(np.random.random_integers(0,10**10))/10**10
y_dot_position = float(np.random.random_integers(0,10**10))/10**10
if x_dot_position ** 2 + y_dot_position ** 2 <= 1:
return 1
else:
return 0
###########################################################
total_points = 1*10**10
paso = 1*10**8
in_circle = 0
for in_este_bucle in xrange(0, total_points, paso):
print "Procesadores disponibles: " + str(multiprocessing.cpu_count())
pool = multiprocessing.Pool()
resultado = pool.map(approx_pi, xrange(in_este_bucle, in_este_bucle + paso))
pool.close()
pool.join()
in_circle += sum(resultado)
del resultado
print 'Total time: ' + str(time.time()-starting_point) +' seconds'
print
print 4.0*in_circle/total_points
答案 1 :(得分:0)
我猜你是否开始涉足蒙特卡罗方法。使用蒙特卡罗方法时,您生成的随机数必须具有均匀分布才能产生精确的近似值。尝试使用:
import random
random.uniform(0,1)
这应该会产生更好的结果。 ivangtorre绝对正确,需要大样本量才能获得准确的近似值。这里是维基百科上蒙特卡罗方法的链接:https://en.wikipedia.org/wiki/Monte_Carlo_method本文的介绍部分正是关于你现在正在做什么的。欢呼声。
编辑:您还可以增加random.uniform(0,1)的范围,然后相应地调整算法以略微提高性能。