Python中的 round() 有两个参数,第一个参数是需要处理的数,第二个参数是数位精度,默认为0。round(3.4)
## 3
round(3.5)
## 4
而有时候会出现奇怪的情况,比如:round(3.24, 1) #是四舍五入
## 3.2
round(3.26, 1) #是四舍五入
## 3.3
round(3.25, 1) #不是四舍五入
## 3.2
###################################
round(0.44, 1) #是四舍五入
## 0.4
round(0.46, 1) #是四舍五入
## 0.5
round(0.45, 1) #是四舍五入
## 0.5
很多人说Python3中采用的是【四舍六入五留双】,上面的例子说明这种说法是不正确的。其实是因为:十进制小数在计算机内是通过二进制小数来近似,在舍和进两个选项中选择更接近的一个
而当舍和进的两个选项十分接近时,round 选择偶数的选项
这就导致出现的结果非常复杂了。
进一步解释:十进制小数 $0.2$ 和 $0.3$ 的二进制表示分别为:
$$
begin{align}
(0.2)_{10} & = left(frac{1}{8}+frac{1}{16}right)+left(frac{1}{128}+frac{1}{256}right)+cdots
=frac{frac{1}{8}+frac{1}{16}}{1-frac{1}{16}}
=frac{3}{15}=frac{1}{5}newline
&=(0.dot{0}dot{0}dot{1}dot{1})_2
end{align}
$$
以及
$$
begin{align}
(0.3)_{10} & = frac{1}{4}+frac{1}{16}+frac{1}{64}cdots
=frac{frac{1}{4}}{1-frac{1}{4}}
=frac{1}{3}newline
&=(0.dot{0}dot{1})_2
end{align}
$$
照第一条规则,由于存在截断,$0.2$ 和 $0.3$ 实际存储的数均小于本身,理应 $0.3$ 更接近 $0.25$。然而可能由于两者和 $0.25$ 的差距都非常小,根据第二条规则选择了前者。
因此实际中使用 round 会遇到不少bug。
在Python中对小数进行四则运算可以考虑使用 decimal 模块。from decimal import Decimal
0.3 - 0.25
## 0.04999999999999999
Decimal(0.3) - Decimal(0.25)
## Decimal('0.04999999999999998889776975375')
Decimal("0.3") - Decimal("0.25")
## Decimal('0.05')
方式二: math.ceil() 向上保留
math 模块的 ceil 函数返回大于等于输入值的最小整数,注意输入值为正或负的情形:from math import ceil
ceil(2.1)
# 3
ceil(-2.1)
# -2
方式三: math.floor() 向下保留
math 模块的 floor 函数返回小于等于输入值的最大整数,注意输入值为正或负的情形:from math import floor
floor(2.1)
# 2
floor(-2.1)
# -3
方式四:int() 保留整数部分
int 纯粹返回整数部分:int(2.1)
# 2
int(-2.1)
# -2
也就是说
$$
text{int}(x)=
begin{cases}
text{math.floor}(x),&xgeq 0newline
text{math.ceil}(x),&x<0
end{cases}
$$
方法五:使用 numpy 模块
numpy 模块中包含上述所有函数,使用该模块最大的好处就是可以作用于数组上!roundimport numpy as np
np.round([2.25, -2.25], 1)
## array([ 2.2, -2.2])ceilnp.ceil([-2.2, 2.2])
## array([-2., 3.])floornp.floor([-2.2, 2.2])
## array([-3., 2.])intnp.trunc([-2.2, 2.2])
## array([-2., 2.])
np.int_([-2.2, 2.2])
## array([-2, 2])numpy 模块中还有一个 rint 函数,返回的是最近的整数:np.rint([-1.45, 1.45])
## array([-1., 1.])
np.int_(np.round(([-1.45, 1.45])))
## array([-1, 1])