我需要编写一个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
。
答案 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 factorint
和limit
参数来阻止它尝试找到大的素因子。请注意,fraction.Fraction
和sympy.Rational
对象始终会自动缩减为最低条款,因此您无需担心这一点。
def is_representable(rational):
d = sympy.Rational(rational).q
return not bool(set(sympy.factorint(d, limit=10).keys()) - {2, 5})