【问题标题】:Euler-Mascheroni Constant欧拉-马斯切罗尼常数
【发布时间】:2021-11-15 21:48:20
【问题描述】:

在编程中,我只使用整数。但这一次进行一些计算。我需要计算 Euler-Mascheroni Constant γ 。直到小数点后第 n 个。{虽然 n ∈ [30, 150] 对我来说已经足够了。

  • [x] = gif(x) = math.floor(x)

但是,我怀疑精度 Numerical Algorithm

我需要使用 Python 获得更高的准确度。

【问题讨论】:

  • 既然它是一个常数,如果您需要它进行其他计算,为什么不在源代码中包含前几百位数字呢?另一方面,如果您需要自己进行近似计算(例如,作为家庭作业项目),那么decimal 模块是您的最佳选择。
  • @JohnColeman(所以你教数学并给我作业????)谢谢!困难在于收敛。
  • 虽然常数可能是一个无理数,但如果您想自己计算该值,您可能还需要考虑使用 Python 的 fractions 模块。这将减少选择特定小数精度的需要。
  • 我懒得写 Python 代码,但是来自Xavier Gourdon and Pascal Sebah 的站点看起来很棒。具体来说,page 的第 6 段给出了超过 1600 位小数的 C 代码...
  • @DarshanPatil:在你的源代码中包含前 150 位数字有什么困难?在源代码中包含前 150 位数字意味着您只需从任何参考源获取前 150 位数字,或者使用 Maple 等专用软件计算一次,然后就完成了。无论您是什么意思,您都不必处理“融合”。

标签: python algorithm math precision floating-accuracy


【解决方案1】:

您可以计算它使用 python Decimal 内置模块来控制您要使用的小数位数 (https://docs.python.org/2/library/decimal.html)。

a = 1/7
len(str(a))-2
Out[1] 17

使用十进制:

from decimal import *
getcontext().prec = 90 #90 decimals precision
a = Decimal(1) / Decimal(7)
len(str(a))-2
Out[2] 90

基本上:

n = 100000
Euler_Mascheroni = -Decimal(log(Decimal(n))) + sum([Decimal(1)/Decimal(i) for i in range(1,n)])
Euler_Mascheroni

Out[3] Decimal('0.577210664893199330073570099082905499710324918344701101627529415938181982282214')

最后,你可以“任意”提高精度:

from decimal import *
from math import log

def Euler_Mascheroni(n,nth_decimals = 80):
    getcontext().prec = nth_decimals
    
    SUM = Decimal(0)
    for i in range(1,n):
        SUM+=Decimal(1)/Decimal(i)
    
    return -Decimal(log(Decimal(n))) + SUM
Euler_Mascheroni(100000000,nth_decimals = 120)

给出:

Decimal('0.5772156599015311156682000509495086978690376512201034388184221886576113026091829254475798266636558124658249350393045066')

回复@Stef 的评论

EM = Decimal(0.57721566490153286060651209008240243104215933593992)#reference taken from wikipedia

n = 100000000
Decimal(log(Decimal(n)))

getcontext().prec = 100
SUM = Decimal(0)
for i in range(1,n):
    SUM+=Decimal(1)/Decimal(i)

EM - (SUM-Decimal(log(Decimal(n))))

会给

Decimal('5.00000174 ... 85E-9')

【讨论】:

  • 您的结果与sympy.EulerGamma.evalf() 不同,从小数点后第 6 位开始:print(sympy.EulerGamma.evalf() - Euler_Mascheroni) 结果为 5.00000833358882e-6。我通过与Wikipedia 给出的 50 位值进行比较来检查,它也从小数点后 6 位开始有所不同。因此,看起来调整模块 Decimal 的小数位数不足以修复近似误差。
  • 其实近似round( (1.-m.gamma(1+1.e-8))*1.e14 )*1.e-6-Decimal(log(Decimal(n))) + sum([Decimal(1)/Decimal(i) for i in range(1,n)])更准确
  • 另外,您使用的是哪个log?我用math.log 来试试你的代码;您唯一的导入是from decimal import *,但模块十进制没有log。我建议使用import decimal as d而不是from decimal import *,这样读者可以更容易地弄清楚你正在使用哪些功能。
  • 你说得对,单靠更多的小数点并不能解决问题,我们需要更多的迭代。通过改进编辑了我的答案。另外,我使用了数学中的日志。问题是关于获取常量的实际值的注意事项,但要计算它,使用任意(30 到 80 位小数)精度。
  • 您使用 100000000 次迭代来获得 5 个小数位的精度。这是一个好兆头,表明该方法效率不高,需要更好的方法。仅当您的方法的精度优于 float 的精度时,才需要使用 Decimal 而不是 float,而这远非目前的情况。
【解决方案2】:

French Wikipedia discussion page,近似到小​​数点后 6 位:

import math as m
EulerMascheroniApp = round( (1.-m.gamma(1+1.e-8))*1.e14 )*1.e-6
print(EulerMascheroniApp)
# 0.577216 

这个常量也可以在 sympy 模块中使用,名称为EulerGamma

>>> import sympy
>>> sympy.EulerGamma
EulerGamma
>>> sympy.EulerGamma.evalf()
0.577215664901533
>>> - sympy.polygamma(0,1)
EulerGamma
>>> sympy.stieltjes(0)
EulerGamma
>>> sympy.stieltjes(0, 1)
EulerGamma

文档:

如果默认的 .evalf() 不够,您可以在最后一个文档链接中找到有关如何更精确地评​​估常量的更多信息。

如果您仍想自己计算常数作为练习,我建议将您的结果与 sympy 的常数进行比较,以检查准确性和正确性。

【讨论】:

  • EulerMascheroniApp = round( (1.-m.gamma(1+1.e-8))*1.e14 )*1.e-6, 中的精度怎么提高?
  • 我尝试使用round函数,并获得了两个位置,但没有更多:g = 0.57721566490153286060651209008240243104215933593992g - round( (1.-m.gamma(1+1.e-8))*1.e14 )*1.e-6 # -3.350984670857926e-07g - round( (1.-m.gamma(1+1.e-8))*1.e15 )*1.e-7 # 6.490153292570966e-08g - round( (1.-m.gamma(1+1.e-8))*1.e16 )*1.e-8 # 3.4901532885989184e-08g - round( (1.-m.gamma(1+1.e-8))*1.e17 )*1.e-9 # 3.390153280324881e-08
  • @Stef 这很有帮助。你真的做到了。谢谢!用于文件。
  • @Stef 最后我安装了 sympy 并且可以接受你的回答?。
猜你喜欢
  • 2012-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-23
  • 1970-01-01
  • 2016-07-11
  • 2021-06-01
相关资源
最近更新 更多