Python程序设计:人工智能案例实践
上QQ阅读APP看书,第一时间看更新

3.11 使用Decimal类型处理货币金额

本节将介绍用于精确货币计算的Decimal类型。如果在银行业或其他需要“精确到分”的领域工作,深入了解Decimal的功能将会为你的工作带来帮助。

对于许多需要使用带小数点数字的科学或数学应用来说,Python的内置浮点数运算已经可以满足需求。例如,当我们说“正常”体温为98.6时,其实际值有可能是98.5999473210643,但其实不需要精确到太多位,数字98.6对于大多数的体温应用来说已经足够了。

在计算机中,浮点值以二进制方式存储(我们在第1章中介绍了二进制,并在在线“数字系统”附录中对其进行了深入讨论)。某些浮点值在转换为二进制值时使用的是其近似值。例如,包含元和分的变量amount,其值为112.31,如果显示变量amount,它看上去是一个精确值,如下:

但是,如果打印出小数点后面的20位,则可以看到内存中的实际浮点值不是精确的112.31,而是一个近似值:

有许多应用程序需要精确表示带小数点的数字。例如,像银行这样每天处理数百万甚至数十亿交易的机构必须将交易“精确到每一分钱”。浮点数可以表示一部分货币金额,但不能表示所有需要精确到分的货币金额。

Python标准库[1]提供了许多可以在Python代码中使用的预定义功能,可以避免重复工作。对于货币计算和其他需要精确表示和操作带小数点数字的应用程序,Python标准库提供了Decimal类型,它使用特殊的编码方案来解决高精度的问题。该方案提供货币计算所需的精度,但需要额外的内存来保存数字以及需要额外的处理时间来执行计算。此外,Decimal类型也提供一些在银行的日常事务中必须用到的其他功能,例如,在计算账户的每日利息时使用的公平的舍入算法[2]

decimal模块导入Decimal类型

之前,我们使用过几个Python内置的类型,如int(用于整数,如10)、float(用于浮点数,如7.5)、str(用于字符串,例如'Python')等。Decimal类型不是Python的内置类型,而是来自Python标准库。Python标准库依据相关的功能被分成不同的模块,decimal是其中的一个模块,定义了Decimal类型及其功能。

要使用Decimal类型,必须首先导入decimal模块,可以导入整个模块,如下:

    import decimal

然后使用decimal.Decimal引用Decimal类型,也可以使用from...import指定要导入的特定功能,如下所示:

这种形式的import语句只导入decimal模块中的Decimal类型,因此可以在代码中直接使用它。我们会在下一章讨论其他形式的import

创建Decimal

通常会使用字符串来创建一个Decimal

在随后的复利计算示例中会使用到变量principalrate

Decimal的算术运算

Decimal支持标准算术运算符+-*///**%,以及相应的增强赋值号:

可以在Decimal和整数之间进行算术运算,但不能Decimal和浮点数之间进行算术运算。

复利问题的需求声明

我们使用Decimal类型提供的精确货币计算功能来计算复利。以下是需求声明:

某人在储蓄账户中存入了1000美元,年利率为5%。假设该人将所有利息留在账户中而不取出,计算并显示10年中每年年底账户中的金额是多少。计算金额时使用下面的公式:

a=p(1 + r)n

其中:

p是存入的初始金额(即本金);

r是年利率;

n是年数;

a是第n年末的存款金额。

计算复利

为了解决这个问题,使用在代码段[5]和代码段[7]中定义的变量principalrate,并利用for语句计算这10年中每年年末的存款金额。对于每一年,循环都会显示一个格式化的字符串,其中包含年份编号和当年年底的存款金额:

代数表达式(1 + r)n表示为

其中,变量rate代表r,变量year代表n

格式化年份和存款金额

语句

使用带有两个占位符的f字符串来格式化循环的输出。

占位符

使用格式说明符“>2”表示显示年份值的字段宽度为2右对齐>)。字段宽度用来指定在显示值时要使用的字符位置数。对于1位数年份值1~9,格式说明符“>2”会在数值前显示一个空格,从而使第一列中的年份右对齐。下图展示了数字1和10在字段宽度为2时的显示效果。

使用“<”则可以实现左对齐

占位符中的格式说明符10.2f,即

    {amount:>10.2f}

amount格式化为浮点数(f)、右对齐(>)、字段宽度为10、保留小数点后两位(.2)。以这种方式格式化所有amount,可以使其像货币金额那样垂直对齐小数点。在10个字符位置中,最右边的三个字符是数字的小数点与后跟在其右侧的两个小数部分的数字。其余7个字符位置是前导空格和小数点左侧的整数部分的数字。在此示例中,所有美元金额在小数点左侧都有四位数,因此每个数字都使用三个前导空格进行格式化。下图显示了值1050.00的格式。


[1] https://docs.python.org/3.7/library/index.html.

[2] 查看更多decimal模块的功能,可以访问https://docs.python.org/3.7/library/decimal.html.