首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python中的二次方程求解器

Python中的二次方程求解器
EN

Code Review用户
提问于 2015-09-05 22:30:12
回答 3查看 5.4K关注 0票数 7

由于我熟悉批处理,所以我专门为os使用模块。单凭Batch不允许我执行更复杂的数学函数,我开始使用Python。

代码语言:javascript
复制
import os
import math
os.system('cls')
os.system('')
os.system('color a')
os.system('title Quadratic Equation Solver') 
#This is used for presentation of the function for WINDOWS cmd
#------------------------------------------------
def QuadSolve():
    os.system('cls')
    print("         Quadratic Equation Solver 1")
    print("")
    print(" X = (-b +/- sqrtb^2 + sqrt4ac)/div/2a ")
    print("")
    print("    Quadratic equation: ax^2 + bx + c")
    print("")
    print("")
    print("")
    a = int(input(" What is the value of a? ---> "))
    b = int(input(" What is the value of b? ---> "))
    c = int(input(" What is the value of c? ---> "))
    firstsec = -1 * b #first second and third "sectors" of the expression
    secsec = math.sqrt(b ** 2 - 4 * a * c)
    thirdsec = 2 * a
    Plussl = firstsec + secsec #Pluss1 is where -b and root b^2 + 4ac are added to give a value of X
    X = Plussl / thirdsec
    Negsl = firstsec - secsec #Same purpose as Plussl but subtraction is used instead to give the other solution of X
    X2 = Negsl / thirdsec
    print("")
    print("         X=%d  OR  X=%d ") % (X, X2)
    os.system('pause >nul')
    QuadSolve()

QuadSolve()

我很想知道是否有人有其他选择。

EN

回答 3

Code Review用户

回答已采纳

发布于 2015-09-05 23:36:04

重复代码无限

现在,为了让QuadSolver永远重复,您正在递归地调用它,方法是在自身内部再次调用QuadSolver。与函数语言不同,函数语言是为尾调用递归优化的,Python不是,一旦在同一个函数中递归1000次,Python就会引发错误。从技术上讲,您可以使用sys.setrecursionlimit设置递归限制,但这是一种非常“麻烦”的方法。

使任何代码段重复可变数量的正确方法是使用while循环。这意味着您的QuadSolver函数的主体应该包装在一个while循环中,如下所示:

代码语言:javascript
复制
def QuadSolver():
    while True:
        # Original code goes here.

通过这样做,您的代码获得了一些好处:

  1. 它将永远正确地执行。
  2. 更快。
  3. 它更具可读性,例如,读者可以清楚地看到,您将永远执行一段代码。

整数输入验证

永远不要信任用户输入正确的输入。例如,如果我运行您的程序并为变量asghiopisdfiojgpfdj输入a怎么办?您的程序会引发ValueError并崩溃。您需要使用try/except块来捕获ValueError,以防用户输入错误的输入。这意味着这里的这一节代码:

代码语言:javascript
复制
a = int(input(" What is the value of a? ---> "))
b = int(input(" What is the value of b? ---> "))
c = int(input(" What is the value of c? ---> "))

应该包装在try/except块中,如下所示:

代码语言:javascript
复制
try:
    a = int(input(" What is the value of a? ---> "))
    b = int(input(" What is the value of b? ---> "))
    c = int(input(" What is the value of c? ---> "))

    # Original code below the above section goes here.
except ValueError:
    print("Please enter a valid integer.")

现在,如果用户输入了不正确的输入,程序会提醒他们注意这一点,然后重新开始。

专用字符串格式

%操作符在Python2.6中不再受欢迎。相反,您应该使用str.format函数。例如,这一行:

代码语言:javascript
复制
print("         X=%d  OR  X=%d ") % (X, X2)

会变成这样:

代码语言:javascript
复制
print("         X={x1}  OR  X={x2}".format(x1=X, x2=X2))

str.format支持以下样式:

  1. 正常参数:"{} {}".format("Hello","world")
  2. 位置参数:"{1} {0}".format("world","Hello")
  3. 命名参数:"{word1} {word2}".format(word1="Hello",word2="world")

您可以使用str.format做更多的事情,但是我将由您来解决这个问题,因为这篇文章的内容太多了。

摆脱了system调用

我发现所有这些代码行都非常可怕:

代码语言:javascript
复制
os.system('cls')
os.system('')
os.system('color a')
os.system('title Quadratic Equation Solver')
os.system('pause >nul')

特别是这一次:

代码语言:javascript
复制
os.system('pause >nul')

这里有很多地方不对劲。首先,对os.system的调用有很长的启动时间和“冷却时间”,例如,它需要相当长的时间。其次,您正在运行的所有命令,比如clscolorpause,都是非常特定于Windows的.如果有人想在基于Linux的系统上运行这个系统,会发生什么呢?大多数这些system调用都是纯风格的,而且无论如何都是不必要的。

关于这一问题:

代码语言:javascript
复制
os.system('pause >nul')

我发现糟糕的C++实践正在泄漏到Python中。上面的方法是缓慢、不安全和不可读的。如果您想暂停直到用户输入,只需使用您的语言的标准输入操作。在Python的例子中,应该是这样的:

代码语言:javascript
复制
input()

如果您仍然出于某种原因使用Python2.x,则如下所示:

代码语言:javascript
复制
raw_input()

真风格

与许多语言不同的是,Python有一个正式的样式指南PEP8,而且您违反了那里设置的大量指南。

  • 变量名应该在snake_case中,如果它们是常量,则在UPPER_SNAKE_CASE中。
  • 函数名应该仅在snake_case中。
  • 类应该在PascalCase中。
  • 在顶层代码/函数/类之间应该有两个空格。

虽然下面的项目实际上不在PEP8中,但它们是一种代码气味,应该删除。

  • 分隔符注释(如下面的注释)应该删除。它们是无用的,在你的代码中看起来很糟糕。#
  • 应该删除代码行末尾的内联注释。如果您必须在代码行的末尾添加注释,那么您可能没有以足够清晰的方式编写代码。如果您觉得需要将注释放在代码行的末尾,那么很可能应该重写这些行。

还值得一提的是文档字符串。Docstring是用Python描述函数和类的一种方便的方法,非常类似于Visual中的XML文档。典型的函数docstring通常如下所示:

代码语言:javascript
复制
def my_function( ... ):
    """Brief description of the function.

    Detailed description of the function.

    argument_name -- Argument description.
    """

如果我们把它应用到您的QuadSolver函数中,我们会得到如下内容:

代码语言:javascript
复制
def quad_solver():
    """Solve the quadratic equation.

    This function takes user input, a, b, and c, and
    runs it through the quadratic equation to "solve"
    it.
    """
    ...
票数 15
EN

Code Review用户

发布于 2015-09-05 22:57:52

这绝不是一个完整的答案,但我也无法控制自己。

print可以处理换行符,因此不需要重复的print语句。

这是:

代码语言:javascript
复制
print("         Quadratic Equation Solver 1")
print("")
print(" X = (-b +/- sqrtb^2 + sqrt4ac)/div/2a ")
print("")
print("    Quadratic equation: ax^2 + bx + c")
print("")
print("")
print("")

可将相同的结果替换为:

代码语言:javascript
复制
print("         Quadratic Equation Solver 1 \n" +
"\n" +
" X = (-b +/- sqrtb^2 + sqrt4ac)/div/2a  \n" +
"\n" + 
"    Quadratic equation: ax^2 + bx + c \n" +
"\n" +
"\n" +
"\n")

当然,这保持了目前的写作方式。

如果您喜欢一行程序,这也是一样的:

代码语言:javascript
复制
print("         Quadratic Equation Solver 1\n\n X = (-b +/- sqrtb^2 + sqrt4ac)/div/2a\n\n    Quadratic equation: ax^2 + bx + c\n\n\n\n")

但是,这将违反PEP8中指出的最大行长。这是否是一个问题取决于你。

票数 8
EN

Code Review用户

发布于 2015-09-06 20:09:02

我不是Pythonista,所以我不能对您对Python的使用做出具体评论。然而,有一个语言独立的问题,现有的答案没有提到。二次方程的代数解是数值分析中一个称为显着性损失问题的典型例子。维基百科关于这个主题的文章详细介绍了这个特殊方程,但是在链接腐烂的情况下进行总结:

bac大得多时,sqrt(b*b - 4*a*c)大约等于abs(b)。这意味着,-b + sqrt(...)-b - sqrt(...)中的一个会减去两个非常相似的数字,结果只会有几个精度。求解代码中的二次方程的正确方法是

代码语言:javascript
复制
det = b*b - 4*a*c
if (det < 0)
    # TODO Decide what you want to do with non-real results. Python supports
    # complex numbers, so you might want to just produce complex results.
else
    s = sqrt(det)
    if (b < 0)
        t = (-b + s) / 2
    else
        t = (-b - s) / 2
    x1 = t / a
    x2 = c / t
票数 8
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/103920

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档