我知道这已经被多次询问了,我遇到过很多博客和SO答案,但是这个让我脱掉了头发。我只想将两位十进制数乘以100,这样我就可以删除它的小数:
>>> 4321.90 * 100
432189.99999999994
>>> Decimal(4321.90) * Decimal(100)
Decimal('432189.9999999999636202119291')
我害怕使用舍入来进行这种看似微不足道的操作。它会安全吗?如果精度问题对我起作用并且结果接近xxx.5怎么办?这会发生吗?我确实理解二进制级别的问题,但我来自C#,我没有.Net的decimal
类型的问题:
decimal x = 4321.90m;
decimal y = 100m;
Console.WriteLine(x * y);
432190,00
我认为Python的十进制模块应该可以解决这个问题。我准备将初始值转换为字符串并使用字符串操作进行数学计算,我对此感到不满......
答案 0 :(得分:4)
它因Python失败的主要原因是因为4321.90
被解释为float(你在那时失去了精度),然后在运行时被转换为Decimal
。 C#4321.90m
被解释为十进制开头。 Python根本不支持小数作为内置结构。
但是使用Python可以轻松解决这个问题。只需使用字符串:
>>> Decimal('4321.90') * Decimal('100')
Decimal('432190.00')
答案 1 :(得分:2)
我要将初始值转换为字符串
是的! (但不要通过调用str
来执行此操作 - 使用字符串文字)
并使用字符串操作进行数学运算
没有!
将十进制值硬编码到源代码中时,应该从字符串文字初始化它,而不是浮点文字。对于4321.90
,已经发生了浮点舍入,并且构建一个Decimal不会撤消该舍入。对于"4321.90"
,Decimal具有您编写的原始文本,可用于执行精确初始化:
Decimal('4321.90')
答案 2 :(得分:1)
Floating point inaccuracy again
Decimal(number)
无法更改内容:在点击Decimal
之前修改了。
您可以通过将字符串传递给Decimal
来避免这种情况,但是:
Decimal("4321.90") * Decimal("100")
结果:
Decimal('432190.00')
(所以Decimal
处理浮点数而不使用浮点寄存器和放大器操作)