Skip to main content
 首页 » 编程设计

python之将欧元转换为欧分时有时会丢失一美分

2025年05月04日17shangdawei

我必须将欧元(字符串)转换为欧分(整数):
例子:


'12,1'=> 1210
'14,51'=> 1451


我使用以下python函数:

int(round(float(amount.replace(',', '.')), 2) * 100) 


但是,用这个数量“ 1229,84”,结果是:122983

更新资料

我使用Wim的解决方案,因为我在Python / Jinja和javascript中都使用整数来表示货币。另请参阅Chepner的答案。

int(round(100 * float(amout.replace(',', '.')), 2)) 


我的问题由我先生回答,他解释了上述结果。

请您参考如下方法:

Docs说了些什么,并有一个简单的解释

我尝试了一下,并对这种情况感到惊讶。所以我转向documentation,里面有一个小字条。


  注意float的round()行为可能令人惊讶:for
  例如,round(2.675,2)给出2.67,而不是预期的2.68。这个
  不是错误:这是由于大多数十进制小数
  不能完全表示为浮点数。


现在,这意味着什么,大多数十进制小数不能表示为浮点数。好的文档后面跟着一个很好的link来解释这一点,但是由于您可能没有来这里阅读一个讨厌的技术文档,所以让我总结一下正在发生的事情。

Python使用IEEE-754浮点标准来表示浮点数。该标准损害了速度的准确性。有些数字无法准确表示。例如,.1实际上表示为0.1000000000000000055511151231257827021181583404541015625。有趣的是,二进制中的.1实际上是一个无限重复的数字,就像1/3是无限重复的.333333一样。



幕后案例研究

现在开始处理您的特殊情况。这很有趣,这就是我发现的。

首先让我们简化您尝试做的事情

>>> amount = '1229,84' 
>>> int(round(float(amount.replace(',', '.')), 2) * 100) 
>>> 122983 


至

>>>int(1229.84 * 100) 
>>> 122983 


有时,Python1无法100%准确地显示二进制浮点数,出于同样的原因,我们无法将分数1/3显示为小数。发生这种情况时,Python将隐藏任何多余的数字。 .1实际上存储为 -0.10000000000000009 2,但是如果您在控制台中键入 int(1.1) - 1.1,Python会将其显示为.1。通过执行 int(myNum) - myNum 3,我们可以看到那些多余的数字。我们可以将此 1229.84公式应用于大多数浮点数,以查看它们后面的多余隐藏数字。4。在您的情况下,我们将执行以下操作。

>>> int(1229.84) - 1229.84 
-0.8399999999999181 


1229.8399999999999181实际上是 122983.99999999999。继续5

>>> 1229.84, 2) * 100 
122983.99999999999 #there's all of our hidden digits showing up. 


现在进入最后一步。这是我们关注的部分。将其更改回整数。

>>> int(122983.99999999999) 
122983 


它向下取整,而不是向上取整,但是,如果我们从未将其乘以100,则最后还有2个9,Python将取整。

>>> int(122983.9999999999999) 
122984 


???现在发生了什么。为什么Python将 122983.9999999999999向下取整,而将 122983.9999999999999向上取整?好吧,每当Python将浮点数转换为整数时,它都会四舍五入。但是,您必须记住,对于Python 122984.0,末尾多两个99是与 122983.9999999999999相同的。

>>> 122983.9999999999999 
122984.0 
>>> a = 122983.9999999999999 
>>> int(a) - a 
0.0 


并且最后没有两个额外的99。

>>> 122983.99999999999 
122983.99999999999 
>>> a=122983.99999999999 
>>> int(a) - a 
-0.9999999999854481 


Python肯定会将 122984.0视为 122983.99999999999,而不是 122983.99999999999。现在回到将 122984转换为整数。因为我们创建了一个小于 122984的小数部分,Python认为这是一个与 122983分开的数字,并且由于强制转换为整数总是会导致Python舍入,因此得到 myFloat.hex()。

ew。要经历很多事情,但是我确实写了很多东西,希望您能做到。所有这些的解决方案是使用 decimal数字而不是浮点数,这会影响精度的速度。

四舍五入怎么办?最初的问题也有一些四舍五入-没有用。见附录6。



解决方案

a)最简单的解决方案是使用 decimal module而不是浮点数。这是在任何财务或会计程序中的首选处理方式。

该文档还提到了我总结的以下解决方案。

b)确切的值可以通过 float.fromhex(myHex)和 myFloat.as_integer_ratio()以十六进制形式表示和检索

c)也可以通过 int(1.1) - 1.1将精确值作为分数检索

d)文档简要提到使用SciPy进行浮点算术运算,但是此 SO question提到SciPy的NumPy浮点数仅是内置浮点类型的别名。 decimal module是更好的解决方案。



附录

1-尽管我经常提到Python的行为,但我所谈论的内容是IEEE-754浮点标准的一部分,这是主流编程语言为其浮点数使用的标准。

2- -0.10000000000000009给我 0.1000000000000000055511151231257827021181583404541015625,但是根据 documentation .1确实是 int(1.1) - 1.1

3-我们使用 int(.1) - .1而不是 int(.1) - .1,因为 int(someNum) -someNum不会给我们隐藏的数字,但是根据文档,它们仍应存在.1,因此我说 int(myNum) - myNum大部分时间都可以工作,但并非始终如此。

4-当我们使用公式 int(3.9)时,发生的事情是将数字转换为整数将使数字向下取整,因此 3变为3,当我们从 3.9减去 -.9时,剩下的是 。但是,由于某种我不知道的原因,当我们除去所有整数,而只剩下小数部分时,Python决定向我们展示一切-整个尾数。

5-这并不会真正影响我们的分析结果,但是当乘以100时,隐藏的数字也会变化一点,而不是将隐藏的数字移动两位小数。

    >>> a = 1229.84 
    >>> int(a) - a 
    -0.8399999999999181 
    >>> a = round(1229.84, 2) * 100 
    >>> int(a) - a 
    -0.9999999999854481 #I expected -0.9999999999918100? 

6 - It may seem like we can get rid of all those extra digits by rounding to two decimal places.

>>> round(1229.84, 2) # which is really round(1229.8399999999999181, 2) 
1229.84 


但是,当我们使用 int(someNum) - someNum公式查看隐藏的数字时,它们仍然存在。

>>> a = round(1229.84, 2) 
>>> int(a) - a 
-0.8399999999999181 


这是因为Python无法将1229.84存储为二进制浮点数。不能做所以...舍入1229.84绝对没有任何作用。