use*_*460 54 python decimal fractions
我想知道如何在Python中将小数转换为最低形式的分数.
例如:
0.25 -> 1/4
0.5 -> 1/2
1.25 -> 5/4
3 -> 3/1
Run Code Online (Sandbox Code Playgroud)
Mar*_*ers 102
您有两种选择:
>>> (0.25).as_integer_ratio()
(1, 4)
Run Code Online (Sandbox Code Playgroud)
(从Python 3.6开始,你可以对一个decimal.Decimal()对象做同样的事情.)
>>> from fractions import Fraction
>>> Fraction(0.25)
Fraction(1, 4)
Run Code Online (Sandbox Code Playgroud)后者有一个非常有用的str()转换:
>>> str(Fraction(0.25))
'1/4'
>>> print Fraction(0.25)
1/4
Run Code Online (Sandbox Code Playgroud)
因为浮点值可能不精确,所以最终会出现"怪异"分数; 限制分母在某种程度上"简化"分数,用Fraction.limit_denominator():
>>> Fraction(0.185)
Fraction(3332663724254167, 18014398509481984)
>>> Fraction(0.185).limit_denominator()
Fraction(37, 200)
Run Code Online (Sandbox Code Playgroud)
如果您仍在使用Python 2.6,那么Fraction()还不支持float直接传入,但您可以将上述两种技术结合到:
Fraction(*0.25.as_integer_ratio())
Run Code Online (Sandbox Code Playgroud)
或者您可以使用Fraction.from_float()类方法:
Fraction.from_float(0.25)
Run Code Online (Sandbox Code Playgroud)
它基本上做同样的事情,例如取整数比率元组并将其作为两个单独的参数传递.
以及带有示例值的小型演示:
>>> 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
Run Code Online (Sandbox Code Playgroud)
无论是fractions模块和float.as_integer_ratio()方法在Python 2.6是新的.
Mat*_*ing 11
由于更复杂的浮点数固有的不精确性,要扩展 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
Run Code Online (Sandbox Code Playgroud)
所需的数学结果是8857097/10000000可以通过转换为字符串然后对其进行操作来实现。
编辑回复
我找到了一种更简单的方法来解决准确性问题。
>>> Fraction(str(f))
Fraction(8857097, 10000000)
Run Code Online (Sandbox Code Playgroud)
转换为字符串还允许准确的 Decimal 实例
>>> Decimal(f).as_integer_ratio()
(1994440937439217, 2251799813685248)
>>> Decimal(str(f)).as_integer_ratio()
(8857097, 10000000)
Run Code Online (Sandbox Code Playgroud)
原始回复
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
Run Code Online (Sandbox Code Playgroud)
现在让我们测试一下:
>>> float_to_ratio(f)
(8857097, 10000000) # mathematically correct
Run Code Online (Sandbox Code Playgroud)
我会注意到这种分数精度没有优化,通常不需要,但为了完整性,它在这里。这个函数不会简化分数,但你可以做额外的处理来减少它:
>>> n = 0.5
>>> float_to_ratio(n)
(5, 10)
>>> Fraction(*float_to_ratio(n))
Fraction(1, 2)
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
如果你想打印一个适当的分数,这个小食谱应该做:
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}")
Run Code Online (Sandbox Code Playgroud)
这将打印如下:
>>> dec_to_proper_frac(3.75)
>>> "3 3/4"
Run Code Online (Sandbox Code Playgroud)