修复函数的奇点

2 投票
6 回答
1754 浏览
提问于 2025-04-16 15:08

假设你有一个这样的函数:

F = lambda x: sin(x)/x

当你计算 F(0.0) 时,会出现“除以零”的警告,并且不会得到预期的结果 1.0。有没有办法写一个叫 fix_singularity 的函数,能够在应用到上面的函数时,给出想要的结果,这样:

fix_singularity(F)(0.0) == 1.0

或者更正式地说,fix_singularity 应该通过以下测试:

import numpy as np

def test_fix_singularity():

    F = lambda x: np.sin(x)/x

    x = np.array((0.0, pi))

    np.testing.assert_array_almost_equal( F(x), [nan, 0] )

    np.testing.assert_array_almost_equal( fix_singularity(F)(x), [1, 0] )

一个可能的实现方式是:

def fix_singularity(F):
    """ Fix the singularity of function F(x) """

    def L(x):
        f = F(x)
        i = np.isnan(f)
        f[i] = F(x[i] + 1e-16)
        return f

    return L

有没有更好的方法来做到这一点?

编辑:还有,我该如何抑制这个警告:

Warning: invalid value encountered in divide

6 个回答

2

一般来说,你不能像想象中那样简单地写一个 修复 装饰器。比如说,一个通用的函数在某些特殊情况下可能并没有一个固定的限制值,就像这个特定的例子一样。

通常的做法是根据具体情况来进行特别处理。

3

如果你已经在使用numpy的话:

a = np.linspace(0.0,2*np.pi,100)
b = np.sin(a)/a

这样计算不会出错,但会在 b[0] 里留下一个 NaN 的值。你可以用下面的代码来替换它,如果你想这样处理的话:

b[np.isnan(b)] = 1.0

更新 如果你想要不显示警告,可以试试:

np.seterr(divide='ignore') # Or possibly np.seterr(invalid='ignore')
7

numpy 有一个叫 sinc() 的函数,这个函数是你提到的函数的标准化形式,也就是说,它是经过处理的版本。

F = lambda x: sin(pi*x) / (pi*x)

这个函数能正确处理 x == 0.0 的情况,也就是当 x 等于零时,它的表现是没问题的。

In [16]: x = numpy.linspace(-1,1,11)

In [17]: print x
[-1.  -0.8 -0.6 -0.4 -0.2  0.   0.2  0.4  0.6  0.8  1. ]

如果你想把它“反标准化”,可以这样做:

In [22]: s = numpy.sinc(x/numpy.pi)

In [23]: print s.round(2)
[ 0.84  0.9   0.94  0.97  0.99  1.    0.99  0.97  0.94  0.9   0.84]

撰写回答