在Python中计算e

时间:2014-05-03 09:29:20

标签: python math python-3.x

表示以下等式的最简单方法是什么?

为了澄清,我的问题是要求一些代码来计算方程的答案。

这有两个问题:

  1. 总和保证无限循环,无法从

  2. 获得答案
  3. 我希望得到一个详尽的答案(可能是40位左右)。

4 个答案:

答案 0 :(得分:5)

如果您需要更高的精确度,可以尝试使用Fraction

from fractions import Fraction # use rational numbers, they are more precise than floats
e = Fraction(0)
f = Fraction(1)
n = Fraction(1)
while True:
    d = Fraction(1) / f # this ...
    if d < Fraction(1, 10**40): # don't continue if the advancement is too small
        break
    e += d # ... and this are the formula you wrote for "e"
    f *= n # calculate factorial incrementally, faster than calling "factorial()" all the time
    n += Fraction(1) # we will use this for calculating the next factorial
print(float(e))

Decimal

from decimal import Decimal, getcontext
getcontext().prec = 40 # set the precision to 40 places
e = Decimal(0)
f = Decimal(1)
n = Decimal(1)
while True:
    olde = e
    e += Decimal(1) / f
    if e == olde: # if there was no change in the 40 places, stop.
        break
    f *= n
    n += Decimal(1)
print(float(e))

所以这里是e在1000个地方:

2.71828182845904523536028747135266249775724709369995957496696762772407663035354759457138217852516642742746639193200305992181741359662904357290033429526059563073813232862794349076323382988075319525101901157383418793070215408914993488416750924476146066808226480016847741185374234544243710753907774499206955170276183860626133138458300075204493382656029760673711320070932870912744374704723069697720931014169283681902551510865746377211125238978442505695369677078544996996794686445490598793163688923009879312773617821542499922957635148220826989519366803318252886939849646510582093923982948879332036250944311730123819706841614039701983767932068328237646480429531180232878250981945581530175671736133206981125099618188159304169035159888851934580727386673858942287922849989208680582574927961048419844436346324496848756023362482704197862320900216099023530436994184914631409343173814364054625315209618369088870701676839642437814059271456354906130310720851038375051011574770417189861068739696552126715468895703 5044

为了更清楚地了解它的作用,这里是它的简化版本:

e = f = 1.0
for i in range(2, 16):
    e += 1.0 / f
    f *= i
print(e)

答案 1 :(得分:3)

显而易见的解决方案是

import math

def e(n=10):
    return sum(1 / float(math.factorial(i)) for i in range(n))

但它在n = 20附近失去了精度(与math.e相比误差大约为10 ^ -16)

40位精度可能是一个挑战,可能需要任意精度算术

我真的没有意识到有这样精确的&#34; e&#34;因为你不能以这样的精度执行任何计算(如果你对它做任何,你会失去那个精度,除非你用任意精度算术做所有事情)。< / p>

答案 2 :(得分:0)

my answer from a question on approximating pi生成类似的结果:

from functools import wraps

def memoize(f):
    """Store and retrive previous results of the decorated function f."""
    cache = {}
    @wraps(f)
    def func(*args):
        if args not in cache:
            cache[args] = f(*args)
        return cache[args]
    return func

@memoize
def fact(n):
    """Recursively calculates n!."""
    if n <= 1:
        return 1
    return n * fact(n - 1)

def inverse_fact_n(start_n=0):
    """Generator producing the infinite series 1/n!."""
    numerator = 1.0
    denominator = start_n
    while True:
        yield numerator / fact(denominator)
        denominator += 1

def approximate_e(steps=None, tolerance=None):
    """Calculate an approximation of e from summation of 1/n!."""
    if steps is None and tolerance is None:
        raise ValueError("Must supply one of steps or tolerance.")
    series = inverse_fact_n()
    if steps is not None: # stepwise method
        return sum(next(series) for _ in range(steps))
    output = 0 # tolerance method
    term = next(series)
    while abs(term) > tolerance: 
        output += term
        term = next(series)
    return output

if __name__ == "__main__":
    from math import e
    print("math.e:\t\t{0:.20f}.".format(e))
    stepwise = approximate_e(steps=100)
    print("Stepwise:\t{0:.20f}.".format(stepwise))
    tolerated = approximate_e(tolerance=0.0000000001)
    print("Tolerated:\t{0:.20f}.".format(tolerated))

函数approximate_e允许您指定:

  1. 一些steps(&#34;我希望它花费这么长时间&#34;);或
  2. 期望的tolerance(&#34;我希望它是准确的&#34;)。
  3. 围绕这个有一些相对高级的Python(例如memoizing装饰器函数和生成系列的生成器函数),但你可以只专注于main函数,其中next(series)为你提供下一个术语总和。

    这给了我输出:

    math.e:     2.71828182845904509080.
    Stepwise:   2.71828182845904553488.
    Tolerated:  2.71828182844675936281.
    

答案 3 :(得分:0)

最有效的方法是使用指数函数的属性。

exp(x)=(exp(x/N))^N

因此,你计算x = exp(2 ^( - n)),其精度比最终结果要求的精度高2n位,并通过将结果平方n次来计算e。

对于小数x,在幂m-1项下截断exp(x)系列的误差小于下一项幂m的两倍。

总而言之,为了以d位的精度/精度计算e,你选择一些中等大n并选择m以便

2^(1-mn)/m! is smaller than 2^(-d-2n)

m的确定也可以动态完成(使用Decimal,如用户22698的答案)

from decimal import Decimal, getcontext


def eulernumber(d):
    dd=d
    n=4
    while dd > 1:
        dd /= 8
        n += 1
    getcontext().prec = d+n
    x = Decimal(1)/Decimal(1 << n)
    eps = Decimal(1)/Decimal(1 << (1 + (10*d)/3 ))
    term = x
    expsum = Decimal(1) + x
    m = 2
    while term > eps:
        term *= x / Decimal(m)
        m += 1
        expsum += term
    for k in range(n):
        expsum *= expsum
    getcontext().prec = d
    expsum += Decimal(0)
    return expsum


if __name__ == "__main__":
    for k in range(1,6):
        print(k,eulernumber(4*k))

    for k in range(10,13):
        print(k,eulernumber(4*k))

带输出

( 1, Decimal('2.718'))
( 2, Decimal('2.7182818'))
( 3, Decimal('2.71828182846'))
( 4, Decimal('2.718281828459045'))
( 5, Decimal('2.7182818284590452354'))
(10, Decimal('2.718281828459045235360287471352662497757'))
(11, Decimal('2.7182818284590452353602874713526624977572471'))
(12, Decimal('2.71828182845904523536028747135266249775724709370'))

请参阅(unix / posix)bc数学库,以获得更专业的实现此思想,也可用于对数和触发函数。指数函数的代码甚至在手册页中作为示例给出。