Python实现小数四舍五入的方法

2019年8月6日 / 50次阅读 / Last Modified 2019年10月23日
数值计算

对小数在Python中实现四舍五入的方法,不能使用round函数,round函数的执行的是HALF EVEN,不是四舍五入(HALF UP)。而使用decimal模块提供的接口,就可以精确实现十进制小数的四舍五入。本文对这个topic进行详细介绍。

Python的浮点数

说到小数,程序员的第一反应可能就是想到了浮点数,小数和浮点数是两个概念。Python中的浮点数,float对象,对应的是机器底层的双精度浮点数。这意味着,float对象的值,并不是一个精确的值!比如:

>>> 0.1 + 0.1 + 0.1 == 0.3
False
>>> 0.1 + 0.2
0.30000000000000004

所以,对于float对象的数值比较操作,要格外小心,原则上浮点数是不能使用 == 来判断的。

浮点数是一个计算机底层概念,它就是代表不精确的小数,因为计算机有表示数据方面的硬件限制(参考:IEEE754浮点数)。而我们日常说的小数,就是带小数点的数。每一个小数,在计算机中,都有一个近似的浮点数的表示!

round函数执行银行家舍入法(HALF EVEN)

round是一个Python的标准内置函数,round在英文里,就是对某个数进行舍入截取的意思,而舍入截取的方式有很多,四舍五入只是其中一种。从Python官方文档的说明中,我们可以知道,round函数执行的是HALF EVEN,而不是四舍五入(HALF UP)

先看几个round函数的整数结果测试用例:

>>> >>> round(-0.5)
0
>>> round(0.5)
0
>>> round(2.5)
2
>>> round(1.5)
2

HALF EVEN的含义,就是在对一个数进行round的时候,如果这个数与两边的数距离相等,就选择偶数。就是上面的例子,对0.5取整,0.5到0的距离与到1的距离相等,于是,round函数就选择了0这个偶数。HALF EVEN被称为银行家舍入法,它的另一条规则是,向最近的数字舍入!

我们再来看几个round函数小数结果的例子:

>>> round(3.48, 1)
3.5
>>> round(3.15, 1)
3.1
>>> round(2.15, 1)
2.1
>>> round(5.15, 1)
5.2

看看高亮的3-6行,round函数都干了些什么......我们要来分别看一下3.48,3.15,2.15以及5.15这四个小数对应的浮点数是什么样的,就明白了:

>>> from decimal import *
>>> Decimal(3.48)
Decimal('3.479999999999999982236431605997495353221893310546875')
>>> Decimal(3.15)
Decimal('3.149999999999999911182158029987476766109466552734375')
>>> Decimal(2.15)
Decimal('2.149999999999999911182158029987476766109466552734375')
>>> Decimal(5.15)
Decimal('5.1500000000000003552713678800500929355621337890625')

decimal模块的Decimal对象,可以将float数据,映射为底层的更精确的表示。

小数3.15的浮点数表示是3.1499999.....保留小数点后1位,向最近的数字舍入,就是3.1;

小数2.15的浮点数表示是2.1499999.....保留小数点后1位,向最近的数字舍入,就是2.1;

round函数没有做错!看起来错在了float对象的不精确表示上面。(计算机无法用二进制来精确的表示十进制的小数)

因此,在一些对精度要求不是很高的地方,我们可以使用round函数来做HALF EVEN的舍入。如果对精度要求很高呢?如果我们就是要对小数3.15做小数点后1位的四舍五入,得到3.2,应该怎么办呢?

用decimal模块的接口做四舍五入

使用decimal模块的接口,可以实现小数精确的四舍五入。decimal模块是Python的一个标准库,是专门为十进制小数的精确计算而设计的。用decimal模块做十进制小数的计算,是符合直觉的:

>>> Decimal('0.1') + Decimal('0.1') + Decimal('0.1') == Decimal('0.3')
True
>>> Decimal('0.1') + Decimal('0.2')
Decimal('0.3')

本文不对decimal模块做过多介绍,只说明如何用它来做小数的精确的四舍五入,请看如下代码:

>>> Decimal('2.15').quantize(Decimal('.0'), rounding=ROUND_HALF_UP)
Decimal('2.2')
>>> Decimal('3.15').quantize(Decimal('.0'), rounding=ROUND_HALF_UP)
Decimal('3.2')
>>> Decimal('3.14159265').quantize(Decimal('.0000'), rounding=ROUND_HALF_UP)
Decimal('3.1416')
>>> Decimal('3.14159265').quantize(Decimal('.000'), rounding=ROUND_HALF_UP)
Decimal('3.142')
>>> Decimal('3.14159265').quantize(Decimal('.00'), rounding=ROUND_HALF_UP)
Decimal('3.14')
>>> str(Decimal('3.14'))
'3.14'

使用quantize成员函数,第1个参数指定了精度,关键是第2个参数,指定了截取的方式,ROUND_HALF_UP,就是四舍五入!最后,可以轻松将Decimal对象转换成字符串。

以上就是对于在Python中实现小数的四舍五入的方法介绍,希望能被您喜欢...

-- EOF --

本文链接:https://www.pynote.net/archives/765

留言区

电子邮件地址不会被公开。 必填项已用*标注


前一篇:
后一篇:

More


©Copyright 麦新杰 Since 2019 Python笔记

go to top