一、一般情况。round(number[, ndigits])函数返回number舍入到小数点后ndigits位精度的值,比如:
round(3.14, 1)
3.1
如果ndigits被省略或为None,则返回最接近number的整数,除此之外,返回值与number的类型一致。
round(3.14, None)
3
round(3.14, 0) # 不是被省略,也不是None
3.0
看看ndigits为负数的情况,同样,结果会被舍入到最接近10的负ndigits次幂的倍数。(负负得正,会对整数位进行舍入)
round(314, -1)
310
二、特殊情况。若number离前后的有效数距离相等时,比如0.5,若保留整数部分,很显然,其离0和离1的距离一样,这个时候round会如何取舍呢?先看看下面实际的运行结果情况:
round(0.5) # 离0和1的距离相等
0
round(-0.5) # 离0和-1的距离相等
0
round(1.5) # 离1和2的距离相等
2
round(2.5) # 离2和3的距离相等
2
round的规则是这样的(python3版本):选择偶数!上面的结果也印证了这一规则。
三、失真情况。一些十进制小数在计算机中无法用二进制精确表示,存在失真,比如3.675,在计算机中的二进制数接近如下情况:
print(f'{3.675:.20f}')
3.67499999999999982236
所以,如果我们采用round函数保留2位小数的话,很显然,计算机认为更接近3.67,验证一下:
round(3.675, 2) # 虽然看起来与3.67、3.68的距离相同
3.67
简单解释一下因为进制转换导致的失真,比如,三分之一,在我们十进制世界里就无法用小数精准表示,即使写成0.33333333,后面加再多的3,依然存在误差。但是在三进制世界里,却可以精准地表示为0.1。
总结:
- round函数与我们现实中的四舍五入规则不一样;
- round函数一直在尽量接近公平,在保留有效位时,会选择离其最近的数;
- 但由于存在进制转换的失真,导致计算远近的时候,可能与我们在十进制世界看到的情况不一样;
- 若离两边数的距离完全相等时,round函数选择偶数;
- 由于round函数的规则比较偏技术,所以一般用在对有效位误差要求不太高的地方,对于有严格精度和规则要求的地方,建议使用decimal模块。
小补充,针对编程小白人员:
round(3.004, 2)
3.0
我要的是保留2位小数,为啥输出的只有一位小数呢?round是不是搞错了?!这里确实冤枉round函数了,round函数按照前面讲的规则计算出结果后,对尾部的非有效位确实清0了,然后函数以浮点数或整数返回,对于返回的结果若用于运算,不会有任何问题,但我们上面看到的“3.0”是格式化打印显示,属于数值的格式化输出范畴,跟round没有关系。更深入一步,round函数也仅对尾部的非有效位清0,而不是真正的截断,一方面,对于数值运算不影响,另一方面,计算机中数值运算的有效位是固定的,就是咱们经常提到的32位或64位(二进制位)。