说明
《Python 教程》 持续更新中,提供建议、纠错、催更等加作者微信: gairuo123(备注:pandas教程)和关注公众号「盖若」ID: gairuo。跟作者学习,请进入 Python学习课程。欢迎关注作者出版的书籍:《深入浅出Pandas》 和 《Python之光》。
Python 的内置函数 round() 返数字舍入到小数点后指定位精度的值。 如果不指定小数位精度,则返回最接近输入值的整数。这是一个数字修约操作。数值修约,是指在进行具体的数字运算前,按照一定的规则确定一致的位数,然后舍去某些数字后面多余的尾数的过程。
如果第三个十进制值大于或等于五,则将数字四舍五入到小数点后两位;否则,数字将向下舍入。例如,1.2345舍入到1.23,1.9876舍入到1.99。
round(1.2345, 2)
# 1.23
round(1.9876, 2)
# 1.99
round(3.14)
# 3
round(0.618)
# 1
它的语法为 round(number, ndigits=None)
,期中 ndigits 是一个,将数字舍入到给定的小数精度。如果省略 ndigits 或无 ndigits,则返回值为整数。否则,返回值的类型与数字相同。ndigits 可能是负的。
对于支持 round() 方法的内置类型,结果值会舍入至最接近的 10 的负 ndigits 次幂的倍数;如果与两个倍数同样接近,则选用偶数。因此,round(0.5) 和 round(-0.5) 均得出 0 而 round(1.5) 则为 2。ndigits 可为任意整数值(正数、零或负数)。如果省略了 ndigits 或为 None ,则返回值将为整数。否则返回值与 number 的类型相同。
对于一般的 Python 对象 number, round 将委托给 number.__round__
,可以类中实现此特殊方法。
对浮点数执行 round() 的行为可能会令人惊讶:例如,round(2.675, 2) 将给出 2.67 而不是期望的 2.68。 这不算是程序错误:这一结果是由于大多数十进制小数实际上都不能以浮点数精确地表示。例如当十进制 2.675转换为二进制浮点数时,它再次被二进制近似值替换,其精确值为:
2.67499999999998223643160599749535322183310546875
因此,四舍五入为 2.67,而不是 2.68。
浮点数在计算机硬件中表示为以 2 为基数(二进制)的小数。由于这个 0.1 无法精确表示 1/10 的值而这个 0.3 也无法精确表示 3/10 的值,使用 round() 函数进行预先舍入也是没用的:
round(.1, 1) + round(.1, 1) + round(.1, 1) == round(.3, 1)
# False
虽然这些小数无法精确表示其所要代表的实际值,round() 函数还是可以用来“事后舍入”,使得实际的结果值可以做相互比较:
round(.1 + .1 + .1, 10) == round(.3, 10)
# True
如果你需要比较高的精度,考虑使用 decimal
模块,它设计用于浮点运算:
from decimal import Decimal
# normal float
num = 2.675
round(num, 2)
# 2.67
# 使用 decimal.Decimal (将浮点作为字符串传递以提高精度)
num = Decimal('2.675')
round(num, 2)
# 2.68
可以自己定义一个方法。一种方法是将移位值加上0.5,然后用 math.floor()
(地板除)。原理是:
简单说就是利用了 int 直接截断的特性,测试如下(以保留两个小数为例):
int(0.115*100+0.5)/100
# 0.12
int(0.125*100+0.5)/100
# 0.13
封装为函数,Python 代码如下:
import math
def round_half_up(n, decimals=0):
multiplier = 10 ** decimals
return math.floor(n*multiplier + 0.5) / multiplier
测试:
round_half_up(0.625, 2)
# 0.63
还有一种办法是用 decimal
模块的 quantize 方法(强烈推荐):
from decimal import Decimal
Decimal(0.625).quantize(Decimal("0.01"), rounding = "ROUND_HALF_UP")
# Decimal('0.63')
其他方法:
import decimal
Decimal('1.115').quantize(Decimal('0.00'), rounding=decimal.ROUND_HALF_UP)
# Decimal('1.12')
Decimal('0.125').quantize(Decimal('0.00'), rounding=decimal.ROUND_HALF_UP)
# Decimal('0.13')
可以再将 Decimal 对象再转为浮点型。
封装为函数如下:
from decimal import Decimal
def round_half_up(n, d):
assert d >= 1, 'd 不能小于1'
assert type(d) == int, 'd 必须为整型'
num = Decimal(str(n))
num = num.quantize(Decimal('0.'+'0'*d),
rounding="ROUND_HALF_UP")
return float(num) if d>1 else int(num)
round_half_up(0.625, 2)
# 0.63
round_half_up(3.14, 1)
# 3
除非对精确度没什么要求,否则尽量避开用round()函数。近似计算我们还有其他的选择:
更新时间:Jan. 29, 2022, 3:59 p.m. 标签:python round 小数点