为什么无论我使用什么数据类型,隐式四舍五入都会向上取整?

4

我一直在尝试修复我的代码中的精度问题,这个问题导致了程序出错。我希望数值被按照我提供的精度呈现,但是似乎 Python 对数字进行了四舍五入。以下是示例:

x = 3069682093880544.81
print (x)
3069682093880545.0
x = Decimal(3069682093880544.81)
print (x)
3069682093880545
x = float(3069682093880544.81)
print(x)
3069682093880545.0
x = Decimal(str(3069682093880544.81))
print(x)
3069682093880545.0
3069682093880545.0
x = str(3069682093880544.81)
print(x)
3069682093880545.0

我想做的就是能够给变量分配精确的值,并在调用时提供相同的值。我做错了什么?
2个回答

6
数字3069682093880544.81正在按照IEEE格式转换为64位浮点数。在该格式中,最接近的数字是43910A47D717A69F。然而,将该数字转换回去后会变成3069682093880544.64。可以看到,小数点后面的最后两个数字已经发生了改变。
IEEE 64位浮点数中的有效数字位数为16位。这很可能是为什么输出结果在16位后停止打印的原因,即3069682093880545。
如果需要更多的小数位数,就需要选择一种不受IEEE浮点数处理方式影响的方法。(请注意,即使源代码解释器也会将数字解析为浮点格式。)如@LeopardShark所提到的。
from decimal import *
print(Decimal("3069682093880544.81"))

将字符串直接转换为十进制数,而不需要将其处理为浮点数。


1
有时候你可以挤出17个数字,但对于这个特定的数字,16确实是极限。你可以通过print([x/10 for x in range(30696820938805440,30696820938805450)])轻松看到它。 - Mark Ransom

5
问题在于字面值3069682093880544.81被解析为float类型。因此,例如您的第二个语句等同于Decimal(float(3069682093880544.81))。你想要的是Decimal("3069682093880544.81"),它将其解析为字符串,然后将其转换为Decimal类型。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接