首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >计算圆周率,得到与帐面不同的值

计算圆周率,得到与帐面不同的值
EN

Stack Overflow用户
提问于 2015-10-12 04:48:36
回答 3查看 1.2K关注 0票数 0

数学常数π(pi)是一个无理数,其数值约为3.1415928。π的精确值等于以下无限和:π=4/1-4/3+4/5-4/7+4/9-4/11+…通过计算前几个项的和,我们可以得到π的一个很好的逼近。编写一个函数approxPi(),该函数将浮点值误差作为参数,并通过逐项计算上述和,在误差范围内逼近常量π,直到当前和与前一和之间的差的绝对值(加上一个较少的项)不大于误差。一旦函数发现差值小于误差,它就应该返回新的和。请注意,此函数不应使用来自数学模块的任何函数或常量。您应该使用所描述的算法来近似π,而不是使用Python中内置的值。

我已经做了下面的程序,但由于某种原因,我得到了与书中的不同的价值。

代码语言:javascript
运行
复制
def pi(error):
    prev = 1
    current = 4
    i = 1
    while abs(current - prev) > error:
        d = 2.0* i +1
        sign = (-1)**i
        prev = current
        current = current + sign * 4 / d
        i = i +1
    return current

output In [2]: pi(0.01)
Out[2]: 3.146567747182955

但是我需要得到这个值

代码语言:javascript
运行
复制
>>> approxPi(0.01)
3.1611986129870506
>>> approxPi(0.0000001)
3.1415928535897395
EN

回答 3

Stack Overflow用户

发布于 2015-10-12 05:28:04

你所使用的近似很难收敛,也就是说,你必须循环很多次才能得到一个合理的值。你看,差别是1/d,这就是精度。您必须循环5000次才能得到四位数,50 k次得到next,500 k得到next,等等(这是数字的指数时间复杂度)。

这可能是你在这里看到不一致的原因之一,你只是得到了四舍五入错误加起来的情况。因为您需要使用那么多的迭代,所以您将永远无法达到所使用的浮点数的全部精度。另一个不一致的原因是,您的引用可能使用了另一个退出条件,您的条件应该小于所提供的错误(理想情况下),并且得到了它(3.146567747182955-pi <0.0 1)。实际上,您的引用似乎使用的是条件abs(current-prev) > 4*error

您使用的公式是,pi=4arctan(1),并使用McLaurin展开的arctan(x)对x的值,这是在收敛的极限。为了获得更好的性能,应该在扩展中使用较低的x。例如,可以使用pi=16arctan(1/5)-4 4arctan(1/239)(这为数字提供了线性时间复杂度):

代码语言:javascript
运行
复制
def pi(error):
    a = 1.0/5
    b = 1.0/239

    prev = 1
    current = 0.0
    i = 0
    while abs(current - prev) > error:
        d = 2.0* i +1
        sign = (-1)**i
        prev = current
        current = current + sign * (16*a - 4*b)/d
        a = a*1.0/(5*5)
        b = b*1.0/(239*239) 
        i = i +1
    return current
票数 3
EN

Stack Overflow用户

发布于 2015-10-12 05:13:00

我想您的函数和approxPi的停止规则是不同的。事实上,你的估计更好。如果您打印出当前的所有值,您将看到,当i= 50时,您的函数将产生所需的输出。但是,它超越了这一点,产生了一个更好的近似。

票数 0
EN

Stack Overflow用户

发布于 2015-10-12 05:54:12

因此,为了得到你正在寻找的答案,提出的问题在描述退出条件方面是错误的。

重新组织得到Pi = 4*(1/1 + 1/3 + 1/5 +.),得到误差为0.01的3.1611986129870506,然后查看后面的项,并在术语< error时停止:

代码语言:javascript
运行
复制
from itertools import count, cycle  #, izip for Py2
def approxPi(error):
    p = 0
    for sign, d in zip(cycle([1,-1]), count(1, 2)):  # izip for Py2
        n = sign / d
        p += n
        if abs(n) < error:
            break
    return 4*p

然后你得到正确的答案:

代码语言:javascript
运行
复制
>>> approxPi(0.01)
3.1611986129870506
>>> approxPi(0.0000001)
3.1415928535897395

使用您的代码(来自@PaulBoddington:Find the value of pi)

代码语言:javascript
运行
复制
def pi(error):
    prev = 0
    current = 1
    i = 1
    while abs(current - prev) > error:
        d = 2.0*i + 1
        sign = (-1)**i
        prev = current
        current = current + sign / d
        i += 1
    return 4*current

注意:这不是当前和以前和之间的区别,所以这个问题是错误的,但是它等于difference_between_sums < error*4。因此,要获得原始代码的正确出口,只需将错误乘以4,例如:

代码语言:javascript
运行
复制
>>> pi(0.04)
3.1611986129870506
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33073467

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档