python 浮点数四舍六入五成双

问题
a = 0.215
b = 0.225
print round(a, 2)
print round(b, 2)

# 执行结果
0.21
0.23
  • 0.215 在进行四舍五入时,保留的两位小数没有进1
  • 0.225 在进行四舍五入时,保留的两位小数可以进1
原因
  • 因为在 Python3 里面,round 对小数的精确度采用了 四舍六入五成双 的方式。

  • 例如对于一个浮点数 a.bcd,需要精确到小数点后两位,那么就要看小数点后第三位:

    • 如果 d 小于 5,直接舍去;
    • 如果 d 大于 5,直接进位;
    • 如果 d 等于 5:
      • d 后面没有数据,且 c 为偶数,那么不进位,保留 c
      • d 后面没有数据,且 c 为奇数,那么进位,c 变成 (c + 1)
    • 如果 d 后面还有非 0 数字,例如实际上小数为 a.bcdef,此时一定要进位,c 变成 (c + 1)
  • 所以,round 给出的结果如果跟设想的不一样,那么需要考虑两个原因:

    • 你的这个小数在计算机中能不能被精确储存?如果不能,那么它可能并没有达到四舍五入的标准,例如 1.115,它的小数点后第三位实际上是 4,当然会被舍去
    • 如果你的这个小数在计算机中能被精确表示,那么,round 采用的进位机制是奇进偶舍,所以这取决于你要保留的那一位,它是奇数还是偶数,以及它的下一位后面还有没有数据
解决四舍五入精度问题
#!/usr/bin/python
# -*- encoding: utf-8 -*-
from decimal import Decimal
import decimal

# 四舍五入,保留2位小数
def setDecimal(data, dec_place='0.00'):
    return Decimal(data).quantize(Decimal(dec_place), rounding=decimal.ROUND_HALF_UP)

a = '0.215'
b = '0.225'

print round(setDecimal(a), 2)
print round(setDecimal(b), 2)

# 输出结果
0.22
0.23
  • 注意:decimal 接收的参数必须是字符串,不能是浮点数;如果是浮点数结果依然不准确
  • 如果你传入的参数为浮点数,并且这个浮点值在计算机里面不能被精确存储,那么它会先被转换为一个不精确的二进制值,然后再把这个不精确的二进制值转换为等效的十进制值
  • 对于不能精确表示的小数,当你传入的时候,Python 在拿到这个数前,这个数就已经被转成了一个不精确的数了。所以虽然参数传入的是 11.245,但是 Python 拿到的实际上是 11.24499999999
上一篇:Oracle计算时间差函数


下一篇:20级训练赛Round #5