Sympy与mpmath计算结果不一致问题求助
mpmath与sympy计算sin(0.4)结果不一致的原因及解决方法
我测试mpmath和sympy时发现,二者计算sin(0.4)的结果存在差异:
- mpmath输出:
0.389418342308650491666311756796 - sympy通过
evalf()、N()或lambdify调用mpmath的输出:0.389418342308650522465285348517
我认为mpmath的结果是正确的,以下是问题根源和解决办法:
测试代码
import sympy as sp import mpmath as mp # 设置mpmath精度为30位小数 mp.mp.dps = 30 print('mp: ', mp.sin('0.4')) # 定义变量并计算正弦函数 x = sp.symbols('x') x = '0.4' print('sp: ', (sp.sin(x).evalf(30))) print('N : ', sp.N(sp.sin(x), 30)) x = sp.symbols('x') sin_func = sp.sin('0.4') # 将sympy函数转为mpmath格式 sin_func_mpmath = sp.lambdify(x, sin_func, modules='mpmath') # 计算结果 result = sin_func_mpmath(mp.mpf('0.4')) print('mo: ', result)
问题原因
问题出在sympy对字符串'0.4'的解析逻辑上:当你调用sp.sin('0.4')时,sympy会先把字符串'0.4'转换为Python原生的双精度浮点数(约15-17位有效数字)。由于二进制浮点数无法精确表示0.4,这个转换过程会引入微小误差。之后sympy基于这个近似值计算正弦,再扩展到30位小数,最终结果自然和mpmath直接用高精度mpf('0.4')计算的结果产生差异。
解决方法
方法1:使用精确的有理数或高精度浮点数作为输入
sympy支持精确的有理数类型,或者直接接收mpmath的高精度浮点数,这样能避免中间的精度损失:
import sympy as sp import mpmath as mp mp.mp.dps = 30 print('mp: ', mp.sin('0.4')) # 用有理数精确表示0.4(2/5) x_rational = sp.Rational(2, 5) print('sp_rational: ', sp.sin(x_rational).evalf(30)) # 直接传入mpmath的高精度浮点数 x_mpf = mp.mpf('0.4') print('sp_mpf: ', sp.sin(x_mpf).evalf(30))
运行后输出会和mpmath的结果完全一致:0.389418342308650491666311756796
方法2:强制sympy使用高精度计算
如果必须使用字符串输入,可以通过配置sympy的计算精度,让它直接基于高精度数值计算:
import sympy as sp import mpmath as mp mp.mp.dps = 30 print('mp: ', mp.sin('0.4')) # 配置sympy的精度为30位 print('sp_high_precision: ', sp.N(sp.sin(sp.nsimplify('0.4')), 30))
这种方式也能得到和mpmath一致的结果。
内容的提问来源于stack exchange,提问作者Samson
相关产品推荐
相关产品推荐

