【问题标题】:This simple Python Fraction Adder is not fully robust and is recieving errors. How can it be improved?这个简单的 Python 分数加法器并不完全健壮,并且会收到错误。如何改进?
【发布时间】:2018-02-24 01:17:57
【问题描述】:

我用 Python 为我的计算机科学课编写了一个分数加法器。但是,我在最终答案缩减过程中遇到了问题。

该过程在 for 循环的开头使用“不等于”比较运算符 != 来测试在除分子和分母时是否会有一个余数。如果有余数(分子 % 分母 ≠ 0),则执行过程:每个除以 n,然后 n 递增,for > 循环再次运行。这种情况一直持续到它们彼此平均分配为止。

首先,我收到一个语法错误:

python FractionAdder.py 2 4 6 8
File "FractionAdder.py", line 23
for ansnum % n != 0 and ansdenom % n != 0:
                ^
SyntaxError: invalid syntax

其次,for 循环并不完全健壮。我的预期目的是将最终答案简化为最简单的形式,但现在,它只是继续增加 n 并减少,直到分子和分母均匀地分开。这是一个问题:3 均分为 6,但 3/6 不是最简单的形式。我可以就如何提高我的程序的稳健性提出一些建议,例如 n 继续增加并且循环继续循环直到实现最简单的形式? (有没有更好的方法来构建我的条件来实现这一点?)

完整代码:

import sys
num1 = int(sys.argv[1])
denom1 = int(sys.argv[2])
num2 = int(sys.argv[3])
denom2 = int(sys.argv[4])

n = 1

# Find common denominators and adjust both fractions accordingly.
while denom1 != denom2:
    denom1 = denom1 * denom2
    num1 = num1 * denom2

    denom2 = denom2 * denom1
    num2 = num2 * denom2

# Add the numerators and set the ansdenom (denom1 and denom2 should be equal by this point if LCD function worked)
ansnum = num1 + num2
ansdenom = denom1

# Reduce the answer.
n = 2
for ansnum % n != 0 and ansdenom % n != 0:
    ansnum = ansnum / n
    ansdenom = ansdenom / n
    n += 1

print("The sum of the two fractions is:" + str(ansnum) + "//" + str(ansdenom))

提前致谢!

【问题讨论】:

  • 我认为你需要一个 while 循环而不是第 23 行中的 for

标签: python math stored-procedures console arithmetic-expressions


【解决方案1】:

您正在尝试编写一个最大公分母查找器,而您的终止条件是错误的。 Euclid's Algorithm反复取两个数的模差,直到结果为0;那么倒数第二个结果是 GCD。标准的python实现看起来像

def gcd(a, b):
    while b:
        a, b = b, a % b
    return a

标准库中已经有一个实现,math.gcd

from math import gcd
import sys

def add_fractions(n1, d1, n2, d2):
    """
    Return the result of n1/d1 + n2/d2
    """
    num   = n1 * d2 + n2 * d1
    denom = d1 * d2
    div   = gcd(num, denom)
    return num // div, denom // div

if __name__ == "__main__":
    if len(sys.argv) != 5:
        print("Usage: {} num1 denom1 num2 denom2".format(sys.argv[0]))
    else:
        n1, d1, n2, d2 = [int(i) for i in sys.argv[1:]]
        num, denom = add_fractions(n1, d1, n2, d2)
        print("{}/{} + {}/{} = {}/{}".format(n1, d1, n2, d2, num, denom))

【讨论】:

  • 最近好像有太多像这样的答案出现在这里。这几乎没有回答这个问题。更不用说它甚至没有明确回答提出的问题(也就是为什么这不起作用),它还提出了一种全新的方式来实现 OPs 要求,忽略 OPs 的代码和心态; SO 不是教程,也不是代码编写服务,因此请不要以这种方式回答不在这些类别下的问题。这将作为答案仅在代码审查时出现
  • 同样,“文档”和“抽象”(仅是建议)应该只是评论,当然不属于答案
  • @Uriel:措辞不好,我已经改进了。另一方面,它准确有效地解决了他正在解决的问题,而不是让他走错方向。
  • 1.我没有给他错误的方向。 2. 为知道编写准确和高效(啊,你正在使用python)代码干杯!但这不是 OP 要求你的
【解决方案2】:

您看到的错误是由错误使用 for 导致的,其中 while 是正确的循环类型(for 用于迭代,while 用于条件)。

尽管如此,您决定共同点的逻辑是有缺陷的,并导致无限循环。请阅读least common multiple,并考虑以下伪代码来确定“新”分子:

lcm = lcm(den1, den2)
num1 *= lcm / den1
num2 *= lcm / den2

【讨论】:

  • 找到除数的最小公倍数是无关紧要的,因为新的分子可能仍然是 LCM 除数的整数倍。例如:3/6 + 6/12 - 除数的 LCM 为 12,结果为 6/12 + 6/12 = 12/12,未减少。正确的程序是计算新的分子和分母,找到 GCD,然后除以,如下面的代码所示。
  • @HughBothwell 我什至没有看过其余的代码,因为它不是问题。他可能没有使用最好的方法,但他显然在学习。如果你试图修复每一个实习生代码,你只会剥夺他们自己改进的动力
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-07
相关资源
最近更新 更多