【问题标题】:converting floats to fractions将浮点数转换为分数
【发布时间】:2020-05-26 19:36:17
【问题描述】:

我正在用 Python3 编写。 我在我的代码中创建了两个列表,我想在循环中将它们“连接”为分数。除了使用 Fractions 库之外,还有其他方法吗?不幸的是,我不能使用它,因为这是任务要求。当分数是浮点数(例如 1/3)时会出现问题。 我怎么解决这个问题?

这是一个例子:

p = [1,2,3]
q = [3,5,9]

frac = []
    for i in p:
      for j in q:
        f = i/j
        if f not in frac:
          frac.append(f)



【问题讨论】:

    标签: python python-3.x fractions


    【解决方案1】:

    你可以使用fractions.Fraction类型。

    1. 使用以下方法导入:from fractions import Fraction
    2. 用分数转换你的 f 方程 f = p/q; f = 分数(p/q)
    3. 然后也使用字符串转换; f = str(分数(p/q))

      from fractions import Fraction
      f = str(Fraction(p/q))
      

    【讨论】:

    • 是的,我知道,但在这个特定的任务中我做不到。
    【解决方案2】:

    如果我理解正确,您的问题不在于“如何将浮点数转换为分数”,而是“如何从数字数组中获取分数的字符串表示形式”,对吧?

    实际上你可以在一行中做到这一点:

    p = [1,2,3]
    q = [3,5,9]
    
    list(map(lambda pair: f"{pair[0]}/{pair[1]}", [(x, y) for x in p for y in q])))
    

    解释:

    map - 接收一个函数和一个迭代器,将迭代器的每个元素传递给该函数。

    [(x, y) for x in p for y in q] - 这是一个list comprehension,它正在为“数组 p 中的每个 x 和数组 q 中的每个 y”生成数对。

    lambda pair - 这是一个anonymous function 接收参数pair(我们知道这将是一个tuple '(x, y)')并返回字符串“x/y”(即“对[0]/对[1]")

    可选程序

    消除分母中的零

    如果你想避免不可能的分数(比如任何超过 0 的分数),列表理解应该是这个:
    [(x, y) for x in p for y in q if x != 0]

    消除重复

    此外,如果您想消除重复项,只需将整个列表包装在 set() 操作中(集合是具有唯一元素的可迭代对象,将列表转换为集合会自动删除重复元素):
    set([(x, y) for x in p for y in q if x != 0])

    消除不必要的重复负号

    列表理解越来越大,但还可以:
    set([(x, y) if x>0 or y>0 else (-x,-y) for x in p for y in q if x != 0])
    解释:如果x>0y>0,这意味着它们中只有一个可能是负数,所以没关系,返回(x,y)。如果不是,那就意味着它们都是负数,所以它们应该是正数,然后返回(-x,-y)。

    测试

    脚本的最终结果是:

    p = [1, -1, 0, 2, 3]
    q = [3, -5, 9, 0]
    
    print(list(map(lambda pair: f"{pair[0]}/{pair[1]}", set([(x, y) if x>0 or y>0 else (-x,-y) for x in p for y in q if y != 0]))))
    
    
    # output:
    # ['3/-5', '2/-5', '1/5', '1/-5', '0/3', '0/9', '2/3', '2/9', '3/3', '-1/3', '-1/9', '0/5', '3/9', '1/3', '1/9'] 
    
    

    【讨论】:

    • 是的,你是对的。谢谢你解决了我的问题。我如何改进您的解决方案,例如将 -1/-6 显示为 1/6。因为在负数的情况下,显示“-”两次是没有意义的。
    • 刚刚将它添加到 awnser,我还修复了第一个过程中的一个错误(消除任何东西上的零)。它应该是相反的“任何大于零的东西”。
    • 感谢您的帮助! :)
    • 很高兴为您提供帮助!如果您能将答案标记为正确的答案,我将不胜感激:) 好好学习!
    【解决方案3】:

    (0.33).as_integer_ratio() 可以解决您的问题。显然0.33 会被任何浮点数替换。

    根据this question

    def float_to_ratio(flt):
        if int(flt) == flt:
            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
    

    这也是一个解决方案。

    【讨论】:

    • 感谢您提供此解决方案。如何改进此代码以以“1/3”而不是“(1, 3)”的方式显示分数。
    【解决方案4】:

    您可以通过下面的简单代码使用循环来计算分数

    x = 0.6725
    a = 0
    b = 1
    while (x != a/b):
        if x > a/b:
            a += 1
        elif x < a/b:
            b += 1
    print(a, b)
    

    a 和 b 的结果是

    269 400
    

    【讨论】:

    • 您的代码使用x = math.pi 需要很长时间。这种寻找有理逼近的蛮力方法效率不高
    • 这是一个非常简单的算法,可以完成这项工作,但效率当然是一种权衡
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-17
    • 1970-01-01
    • 1970-01-01
    • 2012-03-01
    • 1970-01-01
    相关资源
    最近更新 更多