Python 中的浮点到分数转换

问题描述 投票:0回答:2

在练习Python 3.52中的float类型到Fraction类型转换的主题时,我发现了两种不同转换方式之间的区别。

第一种方法是:

>>> 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
python floating-point type-conversion fractions
2个回答
5
投票

这又是因为浮点数不是以 10 为基数(十进制)存储的,而是以 2 为基数(二进制)存储的。

以 10 为底的有限长度数字可能是以 2 为底的重复小数。而且由于浮点数的大小是固定的,因此重复的小数会被截断,从而导致不准确。

当您使用

as_integer_ratio
表示以 2 为基数的重复小数的数字时,由于 10 基数到 2 基数转换中的轻微不准确,您将得到一个有点愚蠢的分数。如果您将这两个数字相除,该值将非常接近您的原始数字。

例如,虽然以 10 为基数的 1/10 = 0.1 并且不是循环小数,但它实际上是以 2 为基数的循环小数。就像以 10 为底的 1/3 = 0.333 一样。

>>> (0.1).as_integer_ratio()
(3602879701896397, 36028797018963968)

如果 Python 的输出是准确的,即使您在提示中只输入

0.1
,您也会看到这一点,得到类似 1.00000...01 的输出。但在一般情况下,Python 会隐藏这种不准确的情况,从而导致混乱。


2
投票

这其实是一个很好的问题。不同结果背后的原因是

x
并不是真正的
1232.23
,因为
1232.23
没有精确的浮点表示,因此
1232.23
最接近的浮点表示的小数表示是
2709702426188841/2199023255552
,但是当您使用
str(1232.23)
它将其视为精确值
1232.23
并返回数字的真实最佳分数表示。

© www.soinside.com 2019 - 2024. All rights reserved.