Python中将浮点数转换为分数

7

在进行Python 3.52中的浮点类型到分数类型转换练习时,我发现了两种不同转换方式之间的差异。

第一种方法是:

>>> from fractions import Fraction
>>> x = 1232.23
>>> f = Fraction(*x.as_integer_ratio())
>>> print(f)
2709702426188841/2199023255552      #Answer

第二种方法是:
>>> from fractions import Fraction
>>> x = 1232.23
>>> f = Fraction(str(x))
>>> print(f)
123223/100                          #Answer

我想知道这两个不同答案背后的原因?如果这个问题很蠢请见谅,我是一个刚接触编程和Python的新手。
编辑:我找到了一种方法,可以通过limit_denominator方法将第一种方法得到的不准确分数转换为准确分数。
>>> from fractions import Fraction
>>> x = 1232.23
>>> f = Fraction(*x.as_integer_ratio())
>>> f = f.limit_denominator(100)     
>>> print(f)
123223/100
2个回答

5
再次出现这种情况是因为浮点数不是以十进制(十进制)而是以二进制(二进制)存储的。在十进制中有限长度的数字在二进制中可能是一个重复的小数。由于浮点数是固定大小的,因此该重复小数被截断,导致精度不准确。
当您对一个在二进制中是重复小数的数字使用as_integer_ratio时,由于从十进制到二进制的转换存在轻微的不准确性,您将得到一个有些愚蠢的分数作为结果。如果您将这两个数字相除,该值将非常接近于您的原始数字。
例如,虽然1/10 = 0.1在十进制中并不是一个重复的小数,但实际上它在二进制中是一个重复的小数。就像1/3 = 0.333...在十进制中一样。
>>> (0.1).as_integer_ratio()
(3602879701896397, 36028797018963968)

如果Python的输出是精确的,那么即使您在提示符中输入0.1,您也会看到这个结果,比如得到类似于1.00000...01的输出。但是,通常情况下,Python会向您隐藏这种不准确性,从而导致混淆。

看起来更准确的答案。这可能是这种异常情况的原因吗? >>> 0.1+0.1+0.1-0.3 5.551115123125783e-17 - Abdul Haseeb
@AbdulHaseeb:那不是真正的原因,原因就像我解释的那样,可以在十进制中表示没有重复小数的数字与可以在二进制中表示的数字是不同的。 - Matti Virkkunen

2
这其实是一个很好的问题。不同结果背后的原因是,x并不真正等于1232.23,因为1232.23没有精确的浮点数表示,所以最接近1232.23的浮点数表示的分数形式是2709702426188841/2199023255552。但当使用str(1232.23)时,它将其视为精确值1232.23并返回数字的真实最佳分数表示形式。

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