Python scipy中exp1的日志

Python scipy中exp1的日志,python,scipy,Python,Scipy,以下 from scipy.special import gamma gamma(x) 大型x溢出。这就是为什么scipy提供了gammaln,它相当于np.log(gamma(x)),允许我们在日志空间中工作并避免溢出 scipy的函数有类似的东西吗?我想要返回与下面相同的内容,但对于大的x,没有下溢: import numpy as np from scipy.special import exp1 def exp1ln(x): return np.log(exp1(x))

以下

from scipy.special import gamma

gamma(x)
大型
x
溢出。这就是为什么scipy提供了
gammaln
,它相当于
np.log(gamma(x))
,允许我们在日志空间中工作并避免溢出

scipy的函数有类似的东西吗?我想要返回与下面相同的内容,但对于大的
x
,没有下溢:

import numpy as np
from scipy.special import exp1

def exp1ln(x):
    return np.log(exp1(x))
(我认为这类似于
gammaln
的原因是
exp1
属于同一个函数族,请参见此处:)

感谢

对于real x,您可以使用log(Ei(x))的系列扩展来表示x→ ∞ (请参阅)对于较大的
x
来说,这是非常精确的

通过一些快速实验,当x>=50(和 这就是
scipy
开始失去全部精度的地方)。而且系列的扩展也很不错, 系数是阶乘数,因此我们可以使用精确的计算,而不会产生灾难性的后果 取消:

def _exp1ln_taylor(x, k):
    r = 0; s = -1
    for i in range(k, 0, -1):
        r = (r + s) * i / x
        s = -s
    return r*s

def exp1ln(x):
    x = np.array(x)
    use_approx = x >= 50

    # Avoid infinity/underflows from outside domain.
    ax = np.where(use_approx, x, 100)
    sx = np.where(use_approx, 1, x)
    approx = -x + -np.log(x) + np.log1p(_exp1ln_taylor(ax, 18))
    sp = np.log(scipy.special.exp1(sx))
    return np.where(use_approx, approx, sp) * 1
与WolframAlpha(可提供数百位数字)的比较:


对于任何想要一个只处理单个数字而不是数组的
exp1ln
版本的人,我采用的解决方案如下:

import numpy as np
from scipy.special import exp1

def _exp1ln_taylor(x, k):
    r = 0
    s = -1
    for i in range(k, 0, -1):
        r = (r + s) * i / x
        s *= -1
    return r * s

def exp1ln(x):
    if x <= 50:
        return np.log(exp1(x))
    else:
        return -x - np.log(x) + np.log1p(_exp1ln_taylor(x, 18))
将numpy导入为np
从scipy.special导入exp1
def_exp1ln_taylor(x,k):
r=0
s=-1
对于范围(k,0,-1)内的i:
r=(r+s)*i/x
s*=-1
返回r*s
def exp1ln(x):

如果x表示复杂的
x
或仅表示真实的
x
?@orlp感谢您忘记指定,那么真实的
x
很漂亮,谢谢!我曾尝试过收敛级数展开,但当它在几项之后还没有接近时就放弃了(就像你链接的文章中所说的那样),甚至从未见过发散级数
import numpy as np
from scipy.special import exp1

def _exp1ln_taylor(x, k):
    r = 0
    s = -1
    for i in range(k, 0, -1):
        r = (r + s) * i / x
        s *= -1
    return r * s

def exp1ln(x):
    if x <= 50:
        return np.log(exp1(x))
    else:
        return -x - np.log(x) + np.log1p(_exp1ln_taylor(x, 18))