Python四舍五⼊函数就⽤round()?四舍五⼊的正确打开⽅式!
round( )函数简介
菜鸟教程中介绍到,round() 函数作⽤就是,返回浮点数x的四舍五⼊值。
> round( x [, n]  )
参数x,n均为数值表达式,返回值为x的四舍五⼊值。n为保留的⼩数位数,不加n则只保留x四舍五⼊后的整数部分。
>>> round(2.3)
2
>>> round(2.45, 1)
菜鸟教程python函数2.5
特殊情况
上⾯的结果并没有错误,这⾥再⽤2.675测试⼀下:
>>> round(2.675, 2)
2.67
显然结果不符合四舍五⼊的规则。为什么会这样呢?原因是:round()函数只有⼀个参数,不指定位数的时候,返回⼀个整数,⽽且是最靠近的整数,类似于四舍五⼊,当指定取舍的⼩数点位数的时候,⼀般情况也是使⽤四舍五⼊的规则,但是碰到.5的情况时,如果要取舍的位数前的⼩数是奇数,则直接舍弃,如果是偶数则向上取舍。
这也就解释了上述现象。可这样⼀来⽤round()函数取浮点数的四舍五⼊值不就变得不可靠了嘛?这样的函数设计的意义何在?⽹上搜了⼀圈答案,觉得这个说法⽐较准确:
python3(注意python2 和 3的round()是不⼀样的,这⾥仅以python3作说明)中round()对浮点数的取舍遵循的是“四舍六⼊五平分”,“五平分”就是根据取舍的位数前的⼩数奇偶性来判断,奇偶平分,符合公平性原则(四舍五⼊不是公平的),这样⼀来也就保证了在数据量较⼤的情况下,筛选数据的真实性。(数学渣,不知道这样理解对否……)
为什么需要平分呢?原因就是部分⼩数⽆法⽤⼆进制完整表⽰,如1.15,转为⼆进制将是很长的⼀串数字:
1.0010011001100110011001100110011001100110011001100110011 这可不是简单的⼏个字节就能存放下的。因此这⾥就出现了取舍的问题。
那么正确的四舍五⼊是否⽆法实现了呢?当然是有解决办法的。⽐如,当你需要四舍五⼊保留两位⼩数的时候,可以将数值乘以100再除以100.0:
>>> round(2.675 * 100)/100.0
2.68
这样可以解决部分浮点数四舍五⼊的问题。为什么是部分呢?笔者发现:
>>> round(2.135*100)/100.0
2.13
检验下过程:
>>> 2.135*100
213.49999999999997
WTF!是精度问题嘛!
>>> Decimal(2.135)*100
Decimal('213.4999999999999786837179272')
⽆法理解是不是!!⼆进制的世界正常⼈真的不懂,盼望⼀下未来有可以直接计算⼗进制的硬件诞⽣吧。
总结
在⽤round()函数进⾏四舍五⼊时,如果你对结果有⼗⾜把握,并且这就是你想要的结果,那就放⼼⼤胆地使⽤。不然就⽼⽼实实写个函数来实现吧,这不是什么难事。