SymPy evalf()采用二进制还是十进制算术?相关差异咨询
SymPy evalf() 相关问题解答
1. SymPy evalf() 采用二进制还是十进制算术?
SymPy的evalf()(包括N())底层依赖mpmath库的十进制多精度浮点算术,并非二进制算术。mpmath的核心类型mpf是十进制浮点数,所有evalf()的计算都是基于十进制精度完成的,这也是官方文档提到“转为浮点近似值(十进制数)”的原因。
2. 为何SymPy需传入Float(value)?
当你直接传入Python原生float类型的value=1.2时,这个值本身是二进制浮点数的近似值——十进制的1.2无法用二进制浮点数精确表示,它实际对应一个接近1.2的分数(比如5404319552844595/4503599627370496)。SymPy会将这个原生float解析为精确的有理数类型,之后evalf()是对这个精确有理数做十进制近似计算。
而SymPy.Float(value)会把原生二进制float转换为SymPy的Float类型(本质是mpmath的mpf十进制多精度浮点数),此时计算的是这个二进制近似值对应的十进制表示,和mpmath直接处理原生float的逻辑一致,所以结果会匹配。
如果想要传入精确的十进制1.2,更推荐使用Float('1.2'),这样能直接创建对应十进制多精度浮点数,避免二进制浮点数的精度损失。
3. mp.mpf(str(value)) 为何会改变mpmath的计算结果?
mp.mpf(value)是把原生二进制float的近似值转换为mpmath的十进制浮点数,而mp.mpf(str(value))是把字符串"1.2"解析为十进制浮点数。这两者的本质是不同的数值:
- 原生
float的1.2是二进制近似,对应分数5404319552844595/4503599627370496; - 字符串
"1.2"解析后是精确的十进制分数6/5,mpmath的mpf可以精确表示这个十进制有限小数。
由于初始输入的数值本质不同,后续的高精度计算自然会从某一位开始出现偏差。
内容的提问来源于stack exchange,提问作者ShoutOutAndCalculate
相关产品推荐
相关产品推荐

