Python中的浮点数转换为比率

10
我试图将一个浮点数表示为两个整数的比值,但是由于某种原因,我得到的整数与我期望看到的相差很大。有人能解释一下吗?
>>> value = 3.2
>>> ratios = value.as_integer_ratio()
>>> ratios
(3602879701896397, 1125899906842624)
>>> ratios[0] / ratios[1]
3.2

我认为(32, 10)(16, 5)是解决这个问题的更好方法。奇怪的是,如果我尝试对像2.5这样的数字做同样的操作,答案正是我所期望的。

>>> value = 2.5
>>> value.as_integer_ratio()
(5, 2)

你期望什么? - aIKid
为什么是 16 / 5 而不是 32 / 10 - qwertynl
(16,5)例如。但我明白为什么会得到如此大的数字。 - itdxer
4
可能重复:关于浮点数运算的所有问题。 - Wooble
我猜这可能会有所帮助。https://dev59.com/o3I95IYBdhLWcg3w5iU4。 - FallenAngel
显示剩余4条评论
3个回答

20

使用fractions模块简化分数:

>>> from fractions import Fraction
>>> Fraction(3.2)
Fraction(3602879701896397, 1125899906842624)
>>> Fraction(3.2).limit_denominator()
Fraction(16, 5)

来自于Fraction.limit_denominator()函数

找到并返回最接近selfFraction,其分母最大为max_denominator。此方法对于寻找给定浮点数的有理逼近非常有用。

浮点数在精度上受到限制,无法准确表示许多数字;您看到的是一个四舍五入的表示,但实际数字是:

>>> format(3.2, '.50f')
'3.20000000000000017763568394002504646778106689453125'

浮点数是由二进制分数的和表示的;1/5 只能通过加上 1/8 + 1/16 + 1/128 + 更多的二进制分数(对于增加的二次幂)来表示。


谢谢,我知道如何用“fractions”来做。我不明白为什么。 - itdxer
没有必要进一步扩展我的回答 - 得到一个“明智”的声誉是一个好的解决方案 :) - Jon Clements

5
这不是16/5,因为3.2并不是完全准确的数字…它是浮点数的粗略近似值… 例如:3.20000000000000017764

但是为什么 2.52.5 相同,而 3.2 不相同呢? - itdxer
@itdxer 我认为当数字的除数是.5时,它们的值相当稳定。它们可以被准确地表示为你所定义的样子。 - aIKid
@itdxer 因为有些数字可以被准确地表示,而有些则不能... 请参考FallenAngel提供的链接 - Jon Clements
1
因为你可以用二进制(基数2)显示整数,但显示小数部分很困难,因为你可能无法在二进制(基数2)中精确地写出一个十进制数。因此,编程语言试图计算最接近您期望结果的值。 - FallenAngel

3

在使用 fractions 模块时,最好提供字符串而不是浮点数,以避免浮点表示问题。

例如,如果您传递 '3.2' 而不是 3.2,则会得到预期结果:

In : fractions.Fraction('3.2')
Out: Fraction(16, 5)

如果你已经将数值存储在变量中,你也可以使用字符串格式化方法。
In : value = 3.2

In : fractions.Fraction(f'{value:.2f}')
Out: Fraction(16, 5)

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