有没有更好的方法可以在一行中计算 π?
Is there a better way to calculate π in one line?
我已经在一行中写了如何在 python 中计算 pi 数的解决方案:
def calc_pi(n=100):
return 4.0 * sum([1 for i in range(n) if hypot(random(), random()) < 1]) / (n + 1)
我想知道是否有更好的解决方案以及如何使其更简单?
P.S。我想练习复杂的单行函数,列表理解等。Monte Carlo方法只是一个例子。
当然有:
import math; print(math.pi)
计算 pi 毫无意义,因为无论您使用什么类型,它都会具有最大精度,并且 math.pi
将同样准确。
一种可以使它更简单的方法是删除列表理解并仅将其设为生成器表达式:
def calc_pi2(n=100):
return 4.0 * sum(1 for i in range(n) if hypot(random(), random()) < 1) / (n + 1)
如果你只是想保存角色,这也行:
def calc_pi3(n=100):
return 4*sum(hypot(random(),random())<1for _ in range(n))/(n+1)
4 * atan(1)
sum([1 for i in range(n) if hypot(random(), random()) < 1]) / n
对于大的n
会倾向于atan(1)
,所以你不妨直接计算一下:
>>> import math
>>> 4 * math.atan(1)
3.141592653589793
它至少看起来像你的公式并且没有明确使用 math.pi
。
顺便说一下,我认为您不应该除以 n+1
,而应该除以 n
。 range(n)
有 n
个元素。
代码改进
此外,您不需要创建一个巨大的列表来计算其总和。 sum
与发电机配合使用效果很好。
我猜你的 hypot
函数使用 sqrt
。不需要它,因为您要与 1
和 sqrt(1) == 1
:
进行比较
>>> from random import random
>>> n = 10000000
>>> 4.0 * sum(1 for i in range(n) if (random()**2 + random()**2) <= 1) / n
3.1418616
如@Blender 所述,您还可以对布尔值求和:
>>> 4.0 * sum((random()**2 + random()**2) <= 1 for _ in range(n)) / n
3.1417656
其他系列
终于有更好的方法了。这个比较慢,但简洁且确定:
>>> 4 * sum(1.0/(2*i + 1)*(-1)**i for i in range(1000000))
3.1415916535897743
还有其他人,faster methods。
我已经在一行中写了如何在 python 中计算 pi 数的解决方案:
def calc_pi(n=100):
return 4.0 * sum([1 for i in range(n) if hypot(random(), random()) < 1]) / (n + 1)
我想知道是否有更好的解决方案以及如何使其更简单?
P.S。我想练习复杂的单行函数,列表理解等。Monte Carlo方法只是一个例子。
当然有:
import math; print(math.pi)
计算 pi 毫无意义,因为无论您使用什么类型,它都会具有最大精度,并且 math.pi
将同样准确。
一种可以使它更简单的方法是删除列表理解并仅将其设为生成器表达式:
def calc_pi2(n=100):
return 4.0 * sum(1 for i in range(n) if hypot(random(), random()) < 1) / (n + 1)
如果你只是想保存角色,这也行:
def calc_pi3(n=100):
return 4*sum(hypot(random(),random())<1for _ in range(n))/(n+1)
4 * atan(1)
sum([1 for i in range(n) if hypot(random(), random()) < 1]) / n
对于大的n
会倾向于atan(1)
,所以你不妨直接计算一下:
>>> import math
>>> 4 * math.atan(1)
3.141592653589793
它至少看起来像你的公式并且没有明确使用 math.pi
。
顺便说一下,我认为您不应该除以 n+1
,而应该除以 n
。 range(n)
有 n
个元素。
代码改进
此外,您不需要创建一个巨大的列表来计算其总和。 sum
与发电机配合使用效果很好。
我猜你的 hypot
函数使用 sqrt
。不需要它,因为您要与 1
和 sqrt(1) == 1
:
>>> from random import random
>>> n = 10000000
>>> 4.0 * sum(1 for i in range(n) if (random()**2 + random()**2) <= 1) / n
3.1418616
如@Blender 所述,您还可以对布尔值求和:
>>> 4.0 * sum((random()**2 + random()**2) <= 1 for _ in range(n)) / n
3.1417656
其他系列
终于有更好的方法了。这个比较慢,但简洁且确定:
>>> 4 * sum(1.0/(2*i + 1)*(-1)**i for i in range(1000000))
3.1415916535897743
还有其他人,faster methods。