欺骗numpy/python来表示非常大和非常小的数字

2024-10-02 08:30:32 发布

您现在位置:Python中文网/ 问答频道 /正文

我需要计算以下函数在从-150开始的范围内的积分:

import numpy as np
from scipy.special import ndtr

def my_func(x):
    return np.exp(x ** 2) * 2 * ndtr(x * np.sqrt(2))

问题是函数的这一部分

^{pr2}$

趋向无穷大——我得到inf,因为x的值小于大约-26。在

这部分的功能

2 * ndtr(x * np.sqrt(2))

相当于

from scipy.special import erf

1 + erf(x)

趋向于0。在

所以,一个非常非常大的数乘以一个非常非常小的数,应该可以得到一个合理大小的数字,但是,相反,python给的是{}。在

我能做些什么来避免这个问题?在


Tags: 函数fromimportnumpyreturnmydefas
3条回答

已经有这样一个函数:^{}。我认为erfcx(-x)应该给你想要的被积函数(注意1+erf(x)=erfc(-x))。在

不知道这会有多大的帮助,但这里有几个想法太长了,不能发表评论。在

你需要计算2 \cdot e^{x^2} \cdot f(\sqrt{2}x)的积分,你correctly identified就是e^{x^2}*(1 + erf(x))。打开括号,你可以把求和的两个部分都积分起来。在

enter image description here

Scipy有这个imaginary error function implemented

第二部分比较困难:

enter image description here

这是一个generalized hypergeometric function。不幸的是,它看起来像scipy does not have an implementation of it,但{a9}声称它确实如此。在

在这里我使用不带常数的不定积分,知道fromto值,很清楚如何使用定积分。在

我认为,@askewchan的解决方案和^{}的组合可以做到:

from scipy.special import log_ndtr

_log2 = np.log(2)
_sqrt2 = np.sqrt(2)

def my_func(x):
    return np.exp(x ** 2) * 2 * ndtr(x * np.sqrt(2))

def my_func2(x):
    return np.exp(x * x + _log2 + log_ndtr(x * _sqrt2))

print(my_func(-150))
# nan

print(my_func2(-150)
# 0.0037611803122451198

对于x <= -20log_ndtr(x)uses a Taylor series expansion of the error function to iteratively compute the log CDF directly,这比简单地取{}要稳定得多。在


更新

正如您在评论中提到的,如果x足够大,exp也可能溢出。虽然您可以使用mpmath.exp来解决这个问题,但是一个更简单、更快的方法是转换成一个np.longdouble,在我的机器上,它可以表示高达1.189731495357231765e+4932的值:

^{pr2}$

相关问题 更多 >

    热门问题