python3:小数位的四舍五入(用两种方法解决round 遇5不进) 您所在的位置:网站首页 一个batch的loss会有小数点后第5位的差距 python3:小数位的四舍五入(用两种方法解决round 遇5不进)

python3:小数位的四舍五入(用两种方法解决round 遇5不进)

2024-05-28 15:42| 来源: 网络整理| 查看: 265

小数位的四舍五入在项目中经常用到,今天群里有人提出1.325 如何才能变成1.33? 当时我一看这么简单,分秒就可以解决:

我回复是这样的的

round(1.315,2)

有个小伙伴 当时就回复: 他要的结果是 1.32, 你打印出是1.31,我看到我想怎么可能呢,我自己运行下, 结果真是1.31 . 我想都没有想,自认为我是对的,好吧,怪不得开发不能测试自己的代码.

我就开始查找原因,我们通过代码进行讲解:

print(Decimal(1.325))

打印结果:

1.3249999999999999555910790149937383830547332763671875

大家看到了吗? 实际1.325用二进制转化的是有精度损失.部分小数无法完全用二进制表示. 这是根本所在.

那有的同学该说了,为什么 有的五能进1 能解释下原理吗? 原理和上边的一样,我举个例子 5可以进1

print(round(1.145,2)) #打印结果 1.15

继续查看二进制保存的值:

print(Decimal(1.145)) #打印结果 1.145000000000000017763568394002504646778106689453125

大家明白了吧 ,round 本身没有问题,而是二进制保存的值有点误差导致的.

有的同学该说了 那怎么避免这种错误 。

我准备了两套方案 1.将数值放大100倍,以利用下面的精确的四舍五入的结果`

def round_up(value): # 替换内置round函数,实现保留2位小数的精确四舍五入 return round(value * 100) / 100.0

应用下 看看结果 如何:

def round_up(value): # 替换内置round函数,实现保留2位小数的精确四舍五入 return round(value * 100) / 100.0 print(round(1.4)) print(round(1.5)) print(round_up(1.115)) print(Decimal(1.115)) #打印结果: 1 2 1.12 1.1149999999999999911182158029987476766109466552734375

看着还不错哦,1.115 居然转化成功了.

2.decimal.Decimal 四舍五入是基于十进制的,在二进制无法精确表示的时候是会有误差的。 任何需要十进制运算的地方,都需要用 decimal.Decimal 取代 float:

from _pydecimal import Decimal, Context, ROUND_HALF_UP print(Context(prec=3, rounding=ROUND_HALF_UP).create_decimal('1.325')) 打印结果: 1.33

自己可以试试其他的值,一定都可以进位.

通过上边的讲解 一定明白 round 本身没有问题,只是float 存储的过程有点误差.

也可以这么解释:

这不是bug,而是一种常见的舍入法,名称是“银行家式舍入法”, 用意是一半舍一半入,如果碰到0.5全入,那么银行觉得自己亏了, 银行希望和用户要风险对半。不光Python,其他的计算机语言都是这个方法, 例如C语言和Basic语言。其实不只是计算机科学,在科学实验的数据处理中,也是采用这种舍入法

推荐第二种方法, 细心的同学可以发现第一种还是不能完成达到5进,自己可以思考下 如果你发现了,可以在下边评论. 谢谢



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有