使用math.log来处理大量数字

时间:2015-10-29 02:18:25

标签: python numpy

我正在使用类似的函数(在评估常量之后):

def n(x):
    return (1.416e-28)*(x**47)*(np.exp(-4.545*x))

X的范围从0到20.中间的x ^ 47项会导致问题;即使第一个和最后一个项在x增加时变得非常小,代码也会在x ^ 47处溢出。

通过进行以下修改,我已经能够将其付诸实践:

def n(x):
    logn=math.log((1.416e-28)*(x**47)*(np.exp(-4.545*x)),x)
    return np.pow(r,logn)

这会返回相当易于管理的数字。

问题是我正在尝试传入一个numpy数组,但math.log只接受标量。此外,numpy似乎没有接受任意基数的日志功能。显然,在numpy中执行此操作的唯一方法是执行以下操作:

np.log(42**3)/np.log(42)

但是如果没有FIRST在基数r处获取日志,它就无法处理大数字。所以numpy不起作用。

我应该只是非pythonic并迭代n(x)fcn吗?

2 个答案:

答案 0 :(得分:2)

ln(a*b) = ln(a) + ln(b)ln(c**d) = d*ln(c)ln(exp(e*f)) = e*f以来,您可以将您的功能重写为:

def n2(x):
    return np.exp(np.log(1.416e-28) + 47*np.log(x) - 4.545*x)

但话虽如此,我发现使用这两种配方在性能方面没有重大差异:

>>> xx = np.linspace(0,20,1000)
>>> q = n(xx[1:])/n2(xx[1:])
>>> np.max(q)
1.0000000000000318
>>> np.min(q)
0.99999999999998357

注意测试中的xx[1:]。这是因为ln(0)未定义,如果您将nan传递给q[0],则xx[0]会导致n2

顺便说一句,您在帖子中提到的向量问题是因为您使用的是math.log而不是np.log

答案 1 :(得分:1)

不要试图一次性计算x**47,而是将其分解。计算它的“一半”,然后在计算“另一半”之前,通过乘以一个小数来减少部分乘积。

# Multiplications are computed left-to-right, so the partial
# product never gets too big.
return 1.416e-28 * x**23 * np.exp(-4.545*x) * x**24