如何将小数转换为分数?

122 投票
6 回答
161479 浏览
提问于 2025-04-18 04:35

我在想怎么把小数转换成最简分数,使用Python来实现。

比如说:

0.25  -> 1/4
0.5   -> 1/2
1.25  -> 5/4
3     -> 3/1

6 个回答

1

这是简单而正确的做法。

使用分数的方法:

from fractions import Fraction
decimals = [0.25, 0.5, 1.25, 3, 0.6, 0.84]

for d in decimals:
    print(Fraction(str(d))) #Cast as string for proper fraction

使用小数的方法:

from  decimal import Decimal
decimals = [0.25, 0.5, 1.25, 3, 0.6, 0.84]

for d in decimals:
    d = Decimal(str(d)) #Cast as string for proper fraction
    nominator,denominator = d.as_integer_ratio()
    if denominator==1:
        print(a)
    else:
        print(nominator,denominator, sep="/")

输出结果:

1/4
1/2
5/4
3
3/5
21/25
7

如果你想打印一个正确的分数,那么这个小方法应该能帮到你:

from fractions import Fraction    

def dec_to_proper_frac(dec):
    sign = "-" if dec < 0 else ""
    frac = Fraction(abs(dec))
    return (f"{sign}{frac.numerator // frac.denominator} "
            f"{frac.numerator % frac.denominator}/{frac.denominator}")

这样打印出来的结果是:

>>> dec_to_proper_frac(3.75)
>>> "3 3/4"
13

为了进一步解释Martijn Pieters的精彩回答,这里提供一个额外的选项,因为更复杂的小数本身就存在不精确的问题。举个例子:

>>> f = 0.8857097
>>> f.as_integer_ratio()
(1994440937439217, 2251799813685248)          # mathematically wrong
>>> Fraction(f)
Fraction(1994440937439217, 2251799813685248)  # same result but in a class
>>> Fraction(f).limit_denominator()
Fraction(871913, 984423)                      # still imprecise

我们想要的数学结果是 8857097/10000000,可以通过将其转换为字符串后再进行处理来实现。

编辑后的回答

我找到了一种更简单的方法来解决这个精度问题。

>>> Fraction(str(f))
Fraction(8857097, 10000000)

将其转换为字符串也可以准确地创建Decimal实例。

>>> Decimal(f).as_integer_ratio()
(1994440937439217, 2251799813685248)
>>> Decimal(str(f)).as_integer_ratio()
(8857097, 10000000)

原始回答

def float_to_ratio(flt):
    if int(flt) == flt:        # to prevent 3.0 -> 30/10
        return int(flt), 1
    flt_str = str(flt)
    flt_split = flt_str.split('.')
    numerator = int(''.join(flt_split))
    denominator = 10 ** len(flt_split[1])
    return numerator, denominator

现在我们来测试一下:

>>> float_to_ratio(f)
(8857097, 10000000)      # mathematically correct

我想说明的是,这种分数精度并不是经过优化的,通常情况下也不需要,但为了完整性,这里还是提到一下。这个函数并没有简化分数,但你可以进行额外的处理来减少它:

>>> n = 0.5
>>> float_to_ratio(n)
(5, 10)
>>> Fraction(*float_to_ratio(n))
Fraction(1, 2)
15
from fractions import Fraction

print(Fraction(0.25))
print(Fraction(0.5))
print(Fraction(1.25))
print(Fraction(3))

#1/4
#1/2
#5/4
#3

当然可以!请把你想要翻译的内容发给我,我会帮你把它变得更简单易懂。

209

你有两个选择:

  1. 使用 float.as_integer_ratio() 方法:

    >>> (0.25).as_integer_ratio()
    (1, 4)
    

    (从 Python 3.6 开始,你也可以 decimal.Decimal() 对象做同样的事情。)

  2. 使用 fractions.Fraction() 类型

    >>> from fractions import Fraction
    >>> Fraction(0.25)
    Fraction(1, 4)
    

后者有一个非常实用的 str() 转换方法:

>>> str(Fraction(0.25))
'1/4'
>>> print Fraction(0.25)
1/4

因为浮点数可能不太精确,所以你可能会得到一些“奇怪”的分数;可以通过 Fraction.limit_denominator() 来限制分母,从而“简化”这个分数:

>>> Fraction(0.185)
Fraction(3332663724254167, 18014398509481984)
>>> Fraction(0.185).limit_denominator()
Fraction(37, 200)

如果你还在用 Python 2.6,那么 Fraction() 还不支持直接传入 float,但你 可以 把上面两种方法结合起来:

Fraction(*0.25.as_integer_ratio())

或者你可以直接使用 Fraction.from_float() 类方法

Fraction.from_float(0.25)

这个方法基本上做的是同样的事情,比如把整数比率的元组作为两个单独的参数传入。

这里有一个小示例,使用你的样本值:

>>> for f in (0.25, 0.5, 1.25, 3.0):
...     print f.as_integer_ratio()
...     print repr(Fraction(f)), Fraction(f)
... 
(1, 4)
Fraction(1, 4) 1/4
(1, 2)
Fraction(1, 2) 1/2
(5, 4)
Fraction(5, 4) 5/4
(3, 1)
Fraction(3, 1) 3

在 Python 2.6 中,fractions 模块和 float.as_integer_ratio() 方法都是新的。

撰写回答