购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

1.4.2 浮点数运算

在实际应用中,特别是涉及金额计算时,我们需要对浮点数执行精确的计算操作,不希望有任何小误差的出现。

浮点数的一个问题是它不能精确地表示十进制数,即使是最简单的数学运算也会产生小的误差,相关代码(accurate_float.py)示例如下:


a = 2.1
b = 4.2
print(a + b)

这些误差是由底层CPU和IEEE 754标准通过自己的浮点运算单位去执行算术运算时产生的。由于Python的浮点数据类型使用底层表示存储数据,因此无法避免这样的误差。

如果想使浮点数运算更加精确(并能容忍一定的性能损耗),可以使用decimal模块,相关代码(accurate_float.py)示例如下:


from decimal import Decimal
a = Decimal('2.1')
b = Decimal('4.2')
print(f'a + b = {a + b}')

初看起来,上面的代码好像有点奇怪,比如用字符串来表示数字。然而,Decimal对象会像普通浮点数一样工作(支持所有的常用数学运算)。如果打印Decimal对象或者在字符串格式化函数中使用Decimal对象,其看起来和普通数字一样。

decimal模块的一个主要特征是允许控制计算的数字位数和四舍五入运算。decimal模块首先创建一个本地上下文并更改它的设置,相关代码(accurate_float.py)示例如下:


from decimal import localcontext
a = Decimal('1.3')
b = Decimal('1.7')
print(f'a / b = {a / b}')
with localcontext() as ctx:
    ctx.prec = 3
    print(f'a / b = {a / b}')

with localcontext() as ctx:
    ctx.prec = 50
    print(f'a / b = { a / b}')

decimal模块实现了IBM的通用小数运算规范。Python新手会倾向于使用decimal模块来处理浮点数的精确运算,不过先理解应用程序的目的是非常重要的。

如果你是在做科学计算、工程领域的计算或电脑绘图,那么使用普通的浮点类型是比较普遍的做法。其中一个原因是,在真实世界中很少要求提供17位精度的计算结果。另一个原因是,原生的浮点数计算要快得多,在执行大量运算的时候速度也是非常重要的。

当然,我们也不能完全忽略误差,也得注意减法、大数和小数加法运算所带来的影响,相关代码示例如下:


num_list = [1.23e+18, 1, -1.23e+18]
print(f'sum result is: {sum(num_list)}')

上述误差可以利用math.fsum()方法来解决,示例如下:


import math
print(f'math sum result: {math.fsum(num_list)}')

对于其他的算法,我们应该仔细研究它并理解它的误差产生来源。

总的来说,decimal模块主要用在涉及金融的领域。在金融领域,哪怕出现小小的误差也是不允许的。Python和数据库打交道的时候通常也会遇到Decimal对象,大多是在处理金融数据的时候。 K8lM7mJzTVz+ar+sVRY+0eIObHCnrovxlYoDk4CK4IKzuJsO4yCKvjjIMgEw228u

点击中间区域
呼出菜单
上一章
目录
下一章
×