python内置方法round()四舍五入方法问题

问题描述
  • 最近在项目中数据出现问题,经过排查,原来是round()惹得祸,如下图所示,round()进行保留位数,并不是按照我们数学上的逻辑四舍五入进行保留
  • 查看官网https://docs.python.org/zh-cn/3/library/functions.html?highlight=round#round,可以看出,这个并不是round函数错误,只能说浮点数在计算机存储是比较特殊,如传入参数2.675,实际计算存储是2.67499999999..., 所以在保留位数时候就会出现问题
问题解决
  • 方案一
def new_round(_float, _len):
    """
    判断需要保留位数后的一位是不是5,如果是5,变成6,在使用round进行四舍五入
    :param _float:
    :param _len:
    :return:
    """

     if isinstance(_float, float) or isinstance(_float, np.float):
        # 小数位数小于保留长度, 直接返回
        if str(_float)[::-1].find('.') <= _len:
            return _float
        if str(_float).split('.')[1][_len] == '5':
            _float = float(str(_float).split('.')[0] + '.' + str(_float).split('.')[1][:_len]+'6')
    elif isinstance(_float, pd.Series):
        _float = _float.apply(lambda x: float(str(x).split('.')[0] + '.' + str(x).split('.')[1][:_len]+'6') \
                              if len(str(x).split('.'))==2 and len(str(x).split('.')[1])>_len and str(x).split('.')[1][_len] == '5' \
                              else x)
    return round(_float, _len)
  • 方案二
def new_round(_float, _len):
    """
    通过Decimal模板进行精确度处理四舍五入
    传入Decimal参数必须是字符串,才能生效
    :param _float:
    :param _len:
    :return:
    """
    _len_str = '0.' + '0' * _len
    if isinstance(_float, float) or isinstance(_float, np.float):
        _float = float(Decimal(str(_float)).quantize(Decimal(_len_str), rounding=ROUND_HALF_UP))
    elif isinstance(_float, pd.Series):
        _float = _float.apply(lambda x: float(Decimal(str(x)).quantize(Decimal(_len_str), rounding=ROUND_HALF_UP)))
    return _float

你可能感兴趣的:(python内置方法round()四舍五入方法问题)