如何使用Python进行准确的十进制计算?

如何使用Python进行准确的十进制计算?

在本文中,我们将学习如何使用Python进行准确的十进制计算。

使用的方法

  • 使用decimal模块的Decimal()函数

  • 使用math模块的fsum()函数

众所周知,浮点数不能准确地表示所有十进制数是一个公认的缺陷。此外,即使是简单的数学计算也会有误差。例如−

示例

以下程序显示浮点数不能准确地表示所有十进制数的能力−

x = 4.2
y = 3.1

# 打印两个变量的总和
print("x + y =", x + y)

# 检查两个变量的总和是否等于7.3
print((x + y) == 7.3)
Bash

输出

执行上述程序将生成以下输出−

x + y = 7.300000000000001
False
Bash

这些错误是CPU构成系统和它的浮点数单元所使用的IEEE 754算术标准的“特点”。如果使用float实例编写代码,因为Python的float数据类型使用本机表示,所以无论如何都无法防止出现这样的错误。

使用decimal模块将以一些性能为代价提供更高的准确性。让我们看看如何做。

方法1:使用decimal模块的Decimal()函数

示例

以下程序演示了使用Decimal()函数执行准确的十进制计算−

# 从decimal模块中导入Decimal
from decimal import Decimal
x = Decimal('4.2')
y = Decimal('3.1')
# 打印两个变量的总和
print("x + y =", x + y)
# 通过将总和传递给Decimal函数检查两个变量的总和是否等于7.3
print((x + y) == Decimal('7.3'))
Bash

输出

执行上述程序将生成以下输出−

x + y = 7.3
True
Bash

在上述代码中,最初指定数字为字符串可能看起来有点奇怪。但是,decimal对象完全按您想要的方式工作(支持所有常见的数学操作等)。当您打印它们或在字符串格式化函数中使用它们时,它们看起来像常规数字。

控制计算的几个方面,例如位数和舍入等,是十进制的一个关键特性。

示例

要执行此操作,请创建一个本地上下文并修改其设置。

# 从decimal模块中导入localcontext
from decimal import localcontext
x = Decimal('2.3')
y = Decimal('2.7')
# 将x除以y(返回浮点数)
print(x / y)
with localcontext() as context:
   # 四舍五入数字,直到3位,即精度为3
   context.prec = 3
   # 将x除以y,精度设置为3
   print(x / y)
Bash

输出

执行上述程序将生成以下输出−

0.8518518518518518518518518519
0.852
Bash

将精度值增加到“60”以获得更高的准确性

示例

# 从decimal模块中导入localcontext
import decimal
from decimal import localcontext
x = decimal.Decimal('2.3')
y = decimal.Decimal('2.7')
# 将x除以y,返回浮点数
print(x / y)
with localcontext() as context:
   # 将数字四舍五入到60位,即精度为60
   context.prec = 60
   # 将x除以y,精度设置为60
   print(x / y)
Bash

输出

执行以上程序,将生成以下输出 −

0.8518518518518518518518518519
0.851851851851851851851851851851851851851851851851851851851852
Bash

方法2:使用 math 模块的 fsum() 函数

decimal 模块实现了 IBM 的 "通用十进制算术规范" 。

不用说,有很多定制选项超出了本文的范围。

Python 初学者可能会试图使用 decimal 模块绕过浮点类型的精度问题。了解你的应用领域也很重要。在处理科学或工程问题、计算机图形或大多数其他科学性质的事物时,使用常规浮点类型更为典型。

例如,实际世界中只有很少的元素以浮点数提供的17位精度进行测量。因此,即使发生微小的计算误差也没有影响。本地浮点类型的速度也明显更快,这在需要进行大量计算时至关重要。

示例

不过,你可能无法完全避免错误。许多算法已经被数学家广泛研究,其中一些算法在处理错误时比其他算法更好。此外,来自诸如减法消除和添加大型和小型数字等做法所导致的结果需要一些注意。

inputList = [1.23e+18, 1, -1.23e+18]

# 查看 sum() 函数在对列表求和时的用法
print(sum(inputList)) 
Bash

输出

在执行以上程序时,将生成以下输出 −

0.0
Bash

fsum() 函数可以在给定范围或可迭代对象之间找到求和。它需要导入 math 库。它在数学计算中被广泛使用。

语法

下面是函数的语法。

maths.fsum( 可迭代对象 )
Bash

可迭代对象可以是范围、数组或列表。

返回类型−

它返回一个浮点数。

示例

下面的示例可以用来解决更准确的 math.fsum() 实现问题 −

# 导入 math 模块
import math
# 输入列表
inputList = [1.23e+18, 1, -1.23e+18]
# 使用 fsum() 函数添加列表元素的总和
print(math.fsum(inputList))
Bash

输出

在执行以上程序时,将生成以下输出 −

1.0
Bash

尽管如此,在处理金融等主题时,使用 decimal 模块最为常见。这样的系统计算中出现微小的不准确是非常不愉快的。

因此,decimal 模块提供了一种避免这种情况的方法。当 Python 与数据库进行交互时,再次遇到 Decimal 对象是很常见的,特别是在访问财务数据时。

结论

本文介绍了通常计算在特定情况下失败的原因以及为什么需要进行正确的十进制计算。我们学习了如何使用两个不同的函数:decimal() 和 fsum() 来执行精确的十进制计算。我们还学习了如何使用 localcontext() 函数来设置结果的精度。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程

登录

注册