Python 的 Decimal的错误计算

摘要 阐述在使用 Python的 Decimal类时,可能产生的错误计算。

详述 BigDecimal 的错误计算 中,笔者较为详细地说明了 Java的 BigDecimal可能出错的原因。类似地,Python的 decimal模块中有个 Decimal类,也可用于高精度的十进制运算,并且能够避免由于浮点数表示不精确带来的精度问题。但是,相仿地,由于有一些参数要设置,所以亦会出现参数不同结果不一致现象。

例1. 不妨重新讨论 计算机的错误计算(一百七十七)中多项式(稍作修改:将小数部分去掉,变成整数)。

已知

计算

代码如下:

python 复制代码
from decimal import Decimal, getcontext
base = Decimal(234) # 定义基数
terms = [ # 计算每一项
    Decimal(134450) * base ** 12,
    Decimal(-31470000) * base ** 11,
    Decimal(2030000) * base ** 10,
    Decimal(1350000) * base ** 9,
    Decimal(1680000) * base ** 8,
    Decimal(1120000) * base ** 7,
    Decimal(748000) * base ** 6,
    Decimal(187000) * base ** 5,
    Decimal(46800) * base ** 4,
    Decimal(-140) * base ** 2,
    Decimal(7666044)]
print(sum(terms)) # 计算总和,输出结果

这时,输出为 1381004:

然而,准确值是 204 . 因此,代码输出的是错误结果。

例2. 用 Python的 Decimal编程计算

代码如下(来源于一大模型):

python 复制代码
from decimal import Decimal, getcontext

getcontext().prec = 50 # 设置精度,这里设置为50位小数

base = Decimal('23.67') # 定义数值
exponent = Decimal('65.5')

part1 = base ** exponent # 计算 23.67^65.5

part2 = (exponent * base.ln()).exp() # 计算 exp(65.5 * ln(23.67))

result = part1 - part2 # 计算差值

print(result)

运行后,输出为 -1E+41(显然是错误结果。正确值是0):

另外,getcontext().prec 不同,那么输出也不同。

点评:

(1)例1可以通过提高精度获得正确结果。

(2)例2不行。

(3)对于例1,虽然可以通过提高精度获得正确值,但是,用户不确定究竟 getcontext().prec 设为多少。只能是通过实验进行猜测。正像有学者评价数学软件一样:"The multiprecision ... in Mathematica and Maple is not very useful ..., because the working precision must be specified by the user and this naturally implies some guess work"[1]。

(4)getcontext().prec 的默认值是28 . 因此,例1中所有运算的结果应该是保留28位十进制有效数字。

参考文献

1\] Cuyt A, Verdonk B, Becuwe S, et al. A remarkable example of catastrophic cancellation unraveled. Computing, 2001, 66: 309--320

相关推荐
2301_809204704 小时前
JavaScript中严格模式use-strict对引擎解析的辅助.txt
jvm·数据库·python
zjy277774 小时前
mysql如何选择合适的索引类型_mysql索引设计实战
jvm·数据库·python
Aaswk4 小时前
Java Lambda 表达式与流处理
java·开发语言·python
万邦科技Lafite4 小时前
京东item_get接口实战案例:实时商品价格监控全流程解析
java·开发语言·数据库·python·开放api·淘宝开放平台
Cyber4K5 小时前
【Python专项】进阶语法-系统资源监控与数据采集(1)
开发语言·python·php
苍煜6 小时前
Java开发IO零基础吃透:BIO、NIO、同步异步、阻塞非阻塞
java·python·nio
AllData公司负责人7 小时前
通过Postgresql同步到Doris,全视角演示AllData数据中台核心功能效果,涵盖:数据入湖仓,数据同步,数据处理,数据服务,BI可视化驾驶舱
java·大数据·数据库·数据仓库·人工智能·python·postgresql
Flittly8 小时前
【LangGraph新手村系列】(5)时间旅行:浏览历史、分叉时间线与修改过去
python·langchain
2301_782040459 小时前
CSS Flex布局中如何实现导航栏与Logo的左右分布_利用justify-content- space-between
jvm·数据库·python
yaoxin5211239 小时前
400. Java 文件操作基础 - 使用 Buffered Stream I/O 读取文本文件
java·开发语言·python