您可以使用fractions module 来检查是否可以表示给定的分数:
from fractions import Fraction
def can_be_represented(num, den):
f = Fraction(num, den)
return Fraction.from_float(float(f)) == f
因为浮点数使用二进制分数,您很快就会发现这可以简化为检查分母是 2 的幂:
def can_be_represented(num, den):
f = Fraction(num, den)
return f.denominator & (f.denominator - 1) == 0
但是,这不会对分子进行任何边界检查,请通过与来自sys.float_info 的信息进行比较来添加边界检查:
import sys
def can_be_represented(num, den):
f = Fraction(num, den)
return (
# denominator is a power of 2
f.denominator & (f.denominator - 1) == 0 and
# numerator exponent can be represented
f.numerator.bit_length() <= sys.float_info.max_exp and
# numerator significant bits can be represented without loss
len(format(f.numerator, 'b').rstrip('0')) <= sys.float_info.mant_dig
)
以上版本测试:
- 分母是 2 的幂
- 分子二进制指数可以表示
- 分子中包含重要信息的部分可以移动以适合浮点数的尾数。
上述优化但可读性较差的版本是:
def can_be_represented(num, den,
_mexp=sys.float_info.max_exp,
_mdig=sys.float_info.mant_dig):
f = Fraction(num, den)
num, den = f.numerator, f.denominator
numbl = num.bit_length()
return (
# denominator is a power of 2
den & (den - 1) == 0 and
# numerator exponent can be represented
numbl <= _mexp and
# numerator significant bits can be represented without loss
(numbl <= _mdig or num << numbl - _mdig >> numbl - _mdig == num)
)