我有一个简单的函数需要评估。
def f0(wt):
term1 = (1 + np.cos(wt)**2) * (1 / 3 - 2 / (wt)**2)
term2 = np.sin(wt)**2
term3 = 4 / (wt)**3 * np.cos(wt) * np.sin(wt)
return 0.5 * (term1 + term2 + term3)
对于wt
的小值(约为1e-4
及以下),我在函数评估中似乎存在数值问题。事实上,term1
和term3
具有非常大而且几乎相反的值,但term2
非常小。
我认为通过将这三个术语的总和分成两部分,如此处所示,我稍微改进了一些东西。
def f1(wt):
# Split the calculation to have more stability hopefully
term1 = (1 + np.cos(wt)**2) * (1 / 3 - 2 / (wt)**2)
term2 = np.sin(wt)**2
term3 = 4 / (wt)**3 * np.cos(wt) * np.sin(wt)
partial = term1 + term3
return 0.5 * (partial + term2)
然而,对于非常小但正的wt
值,我认为仍然存在数值问题。我期望此函数对于任何正值的wt
都是平滑的,但是,如您所见,从附加的绘图中可以看到,在1e-3
以下的值存在不连续的异常情况。
我的问题是:如果我已经使用了float64
数据类型,那么如何提高Numpy的数值精度?
注意:我使用的是64位Windows 10机器。我在其他Stack Overflow线程上读到,类np.float128
不可用。
完整代码片段
import numpy as np
import matplotlib.pyplot as plt
wt = np.logspace(-6, 1, 1000)
def f0(wt):
term1 = (1 + np.cos(wt)**2) * (1 / 3 - 2 / (wt)**2)
term2 = np.sin(wt)**2
term3 = 4 / (wt)**3 * np.cos(wt) * np.sin(wt)
return 0.5 * (term1 + term2 + term3)
def f1(wt):
# Split the calculation to have more stability hopefully
term1 = (1 + np.cos(wt)**2) * (1 / 3 - 2 / (wt)**2)
term2 = np.sin(wt)**2
term3 = 4 / (wt)**3 * np.cos(wt) * np.sin(wt)
partial = term1 + term3
return 0.5 * (partial + term2)
plt.figure()
plt.loglog(wt, f0(wt), label='f0')
plt.loglog(wt, f1(wt), label='f1')
plt.grid()
plt.legend()
plt.xlabel('wt')
plt.show()