我刚用两种方法算了同一个数字,但在numpy中出现错误。
[[ 0.910221324013388510820732335560023784637451171875]]
[[-0.9102213240133882887761274105287156999111175537109375]]
这个数字在e^(-15)之前是一样的,但之后就不同了。我该如何处理这个误差?有没有办法限制浮点数的精度呢?
因为我使用这些数字来计算指数函数,即使是微小的差异也会导致令人沮丧的错误...
我刚用两种方法算了同一个数字,但在numpy中出现错误。
[[ 0.910221324013388510820732335560023784637451171875]]
[[-0.9102213240133882887761274105287156999111175537109375]]
这个数字在e^(-15)之前是一样的,但之后就不同了。我该如何处理这个误差?您是关心结果的实际精度,还是只想从两个计算中获得相同的数字?
如果您只想要相同的数字,可以使用np.around()
将结果四舍五入到一定的小数位数。但是,这样做只会降低结果的精度。
如果您真的想更精确地计算结果,可以尝试使用np.longdouble
类型作为输入数组,根据您的架构和编译器,可能会给您提供一个80或128位的浮点表示,而不是标准的64位np.double*
。
您可以使用np.finfo
比较近似的小数位数精度:
print np.finfo(np.double).precision
# 15
print np.finfo(np.longdouble).precision
# 18
然而,一些编译器(如Microsoft Visual C++)始终将long double
视为与double
同义词,在这种情况下,np.longdouble
和np.double
之间的精度没有区别。
numpy.longdouble
是指你的C编译器所称的long double
类型”,那么不幸的是,对于一些C编译器来说,它并不比double
更精确(例如Visual Studio)。尽管如此,还是要为回答问题点赞。 - Pascal Cuoqnp.longdouble
报告为numpy.float128
,但它是错误的——它仍然是旧的80位x87扩展精度类型,填充了6个零字节。(同样,32位Linux经常将相同的类型报告为numpy.float96
。) - Mark Dickinson# The library mpmath is a good solution
>>> import sympy as smp
>>> import mpmath as mp
>>> mp.mp.dps = 50 # Computation precision is 50 digits
# Notice that the difference between x and y is in the digit before last (47th)
>>> x = smp.mpmath.mpf("0.910221324013388510820732335560023784637451171875")
>>> y = smp.mpmath.mpf("0.910221324013388510820732335560023784637451171865")
>>> x - y # Must be equal to 1e-47 as the difference is on the 47th digit
mpf('1.000014916280995001003481719184726944958705912691304e-47')
使用numpy您无法做得更好。您可以使用更高的精度计算指数。
>>> smp.exp(x).evalf(20)
2.4848724344693696167
请注意,在SymPy 0.7.6版本之后,mpmath不再与SymPy一起打包,而是成为其依赖项。 这意味着在更新的SymPy版本中,sympy.mpmath
函数已经移动到了mpmath
。