确定python分数是否可以具有等效的小数

时间:2017-02-02 08:57:40

标签: python math sympy

我需要编写一个python函数,它接受类“Fraction”类的对象作为参数,并确定该分数是否可以用十进制格式表示。例如,1/2可以用0.5表示,但1/3没有带有限位数的十进制等值(0.333333333是近似值)。

我的方法是将分数与分子除以分母进行比较如下(假设“frac”是分数对象):

 if frac == frac.numerator / frac.denominator:
      print('has decimal representaion')
 else:
      print('has no decimal representation')

但在许多情况下这不起作用。例如,Python错误地比较Fraction(347, 1000) == 0.347,它返回False,尽管它应该是True。 我知道python有一个与浮点运算有关的问题,因此我正在寻找解决这个问题的解决方法或包。

注意:我使用了sympy但同意比较S(1)/3 == 1/3返回True,我需要False

2 个答案:

答案 0 :(得分:8)

使用此:

  

如果分母具有除2和5之外的任何素因子,则它不具有精确的十进制表示。 - khelwood

您可以通过将2s除以5s然后检查结果是否为1来测试:

def has_decimal_representaion(frac):
    d = frac.denominator
    for n in (2, 5):
        while d % n == 0:
            d = d / n
    return d == 1

答案 1 :(得分:1)

检查Fraction(1, 3) == float(1/3)的问题是float(1/3)在技术上也是一个有理数,因为它是一个有限表示的浮点数。确保有理数为6004799503160661/18014398509481984

>>> (1/3).as_integer_ratio()
(6004799503160661, 18014398509481984)

此方法仅在计算机可以为浮点数存储无限多个数字时才有效,这是不可能的。

至于khelwood建议的更简单的测试,如果分母有2或5以外的因子,你可以使用SymPy factorintlimit参数来阻止它尝试找到大的素因子。请注意,fraction.Fractionsympy.Rational对象始终会自动缩减为最低条款,因此您无需担心这一点。

def is_representable(rational):
    d = sympy.Rational(rational).q
    return not bool(set(sympy.factorint(d, limit=10).keys()) - {2, 5})