先看代码:
print("float,22.95保留1位小数" ,float('%.1f' % float(22.95)))
print("float,22.85保留1位小数" ,float('%.1f' % float(22.85)))
print("round保留一位小数:" ,round(22.95, 1))
# float,22.95保留1位小数 22.9
# float,22.85保留1位小数 22.9
# round保留一位小数: 22.9
惊奇的发现22.95四舍五入后结果为22.9;竟然和22.85四舍五入结果一样。
round( )函数简介
菜鸟教程中介绍到,round() 函数作用就是,返回浮点数x的四舍五入值。返回值为x的四舍五入值。n为保留的小数位数,不加n则只保留x四舍五入后的整数部分。
特殊的情况,不是四舍五入
显然结果不符合四舍五入的规则。为什么会这样呢?原因是:round()函数只有一个参数,不指定位数的时候,返回一个整数,而且是最靠近的整数,类似于四舍五入,当指定取舍的小数点位数的时候,一般情况也是使用四舍五入的规则,但是碰到.5的情况时,如果要取舍的位数前的小数是奇数,则直接舍弃,如果是偶数则向上取舍。
小数位的四舍五入在项目中经常用到,这就是上面提出22.95变成了22.9,那 如何才能变成23.0呢?
查找原因
通过Decimal函数查找下原因
print(Decimal(22.95))
print(Decimal(22.85))
# 22.949999999999999289457264239899814128875732421875
# 22.85000000000000142108547152020037174224853515625
根本原因:实际22.95用二进制转化的是有精度损失.部分小数无法完全用二进制表示。
这也就是为什么有的5可以进,有的就不行,如上代码22.85就可以正常进位。
round 本身没有问题,而是二进制保存的值有点误差导致的.
正确的解决方法
from decimal import Decimal, ROUND_HALF_UP
def numTrans(n, d=2):
s = '0.' + '0' * d
return Decimal(str(n)).quantize(Decimal(s), rounding=ROUND_HALF_UP)
print("numTrans22.95保留1位:",numTrans(22.95,1))
# numTrans22.95保留1位: 23.0