引入
在Python中,负责四舍五入的函数是round(),很多人都会,它的用法如下:
round(number, ndigits)
其中,number是要四舍五入的数字,ndgigits是要四舍五入的位数(小数点后计算),不填默认为四舍五入到个位,例如:
或者:
print('%.你四舍五入的位数f' % 你要四舍五入的数)
print('{:.你要四舍五入的位数f}'.format(你要四舍五入的数))
print(f'{你要四舍五入的数:.2f}')
但是,显然没有这么简单,在有些数中,可能会:
其他方法也是如此,下面就是我们的解决方案
解决方案
分析原因
其实原因很简单,在Python中,采用的是二进制运算,如果把1.035转为四舍五入20位(此处不能用round函数),执行:
print(f'{1.035:.20f}')
你应该会看到:1.03499999999999992006,这其实是Python进制转换的误差,如果四舍五入到第二位,第三位是4,小于5,会舍去,所以就会产生误差
处理方法
我们只需要使用Python内置的十进制运算(decimal)模块就可以了
import decimal # 导入decimal模块
n = decimal.Decimal('1.035') # 定义一个decimal.Decimal类型的变量n,值为1.035,必须是字符串
第三行的值必须要是字符串,不然还会有错,接下来,直接round就行
print(round(n, 2))
但是如果你的值是1.025,结果依旧为1.02,其实原因很简单,decimal模块默认四舍五入机制为:
如果5前一位是奇数,则进位,否则,舍去,解决方法也很简单,在import decimal下面,加一行代码:
decimal.getcontext().rounding = decimal.ROUND_HALF_UP
然后,结果就正确了。
我还写了一段代码,生成一个csv文件,可以看到各种算法的结果:
import decimal
decimal.getcontext().rounding = decimal.ROUND_HALF_UP
dn = decimal.Decimal('1.005')
n = 1.005
with open("四舍五入.csv", "w", encoding='utf-8') as f:
f.write("base,round,f-string,decimal\n")
for i in range(10):
with open("四舍五入.csv", "a", encoding='utf-8') as f:
f.write(f"{n+(i/100)},{round(n+(i/100), 2)},{n+(i/100):.2f},{round(dn+decimal.Decimal(i/100), 2)}\n")
print("已将结果保存到四舍五入.csv")
用Excel或WPS打开生成的文件,你可以看到:
base是原数,可以看到,只有decimal的结果是准确的。