在很多人眼里,round可能是一个四舍五入函数,但到了python3当中并没有你想的那么简单,这已经不再是一个高精度的四舍五入函数了,可能计算的结果会让你出乎意料。
首先看一段代码:
# coding=utf-8 a = 1.2345 b = 1.23456 c = 1.2335 print(str(a) + "取后三位结果: " + str(round(a, 3))) print(str(b) + "取后三位结果: " + str(round(b, 3))) print(str(c) + "取后三位结果: " + str(round(c, 3)))
运行结果:
1.2345取后三位结果: 1.234
1.23456取后三位结果: 1.235
1.2335取后三位结果: 1.234
发现python3并没有进行四舍五入,为什么呢?
去翻阅python3的文档,有这么一段话:
values are rounded to the closest multiple of 10 to the power minus ndigits; if two multiples are equally close, rounding is done toward the even choice.
大概意思是:如果距离两边一样远,会保留到偶数的一边。
比如round(0.5)和round(-0.5)都会保留到0,而round(1.5)会保留到2
那么根据这个解释来讲,a b c的结果都应该是1.234的,但目前就a和c取值正确,b为啥会出现1.235呢?继续往下看
文档里面还写到:
The behavior of round() for floats can be surprising: for example, round(2.675, 2) gives 2.67 instead of the expected 2.68. This is not a bug: it’s a result of the fact that most decimal fractions can’t be represented exactly as a float.
大概意思是:这不是个bug,而是大部分情况下小数部分转成二进制后会丢失精度。
例如:计算机将1.23456转成二进制,这时候二进制比1.23456略大一丢丢 … (比如1.23456000000000001)
计算机不得不将第四位小数进一处理,导致出现了现在的结果:1.2345
如果还不明白,继续往下看
# coding=utf-8 a = 1.23450000000000 b = 1.23450000000001 c = 1.23449999999999 print(str(a) + "取后三位结果: " + str(round(a, 3))) print(str(b) + "取后三位结果: " + str(round(b, 3))) print(str(c) + "取后三位结果: " + str(round(c, 3)))
可以不去执行,先自己猜一下结果,然后再去验证
先记住“如果距离两边一样远,会保留到偶数的一边。”这句话,然后往下看:
- a: 小数第三位往后的值是 0.0005,如果第三位是偶数则丢弃,是奇数则进一,最后发现第三位小数是4,属于偶数。结果是:1.234
- b: 小数第三位往后的值是 0.00050000000001,并不满足距离两边一样远,进一。结果应该是1.235
- c: 小数第三位往后的值是 0.00049999999999,并不满足距离两边一样远,舍弃,结果应该是1.234
执行这段python代码,运行结果:
- 1.2345取后三位结果: 1.234
- 1.23450000000001取后三位结果: 1.235
- 1.23449999999999取后三位结果: 1.234
最后:如果对精度要求不大,可以用round函数,但如果有四舍五入的需求且对精度要求高,可以考虑decimal模块。
评论前必须登录!
注册