7
\$\begingroup\$

I use the module os specifically for Windows since I am familiar with Batch. Batch alone didn't allow me to execute more complicated mathematical functions, I began to use Python.

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()

I am very interested to know if anyone has any alternatives.

\$\endgroup\$

migrated from stackoverflow.com Sep 6 '15 at 0:38

This question came from our site for professional and enthusiast programmers.

  • \$\begingroup\$ err, how are we measuring better? In terms of coding alternatives, prettier, imho, see this \$\endgroup\$ – Shawn Mehan Sep 5 '15 at 22:32
  • \$\begingroup\$ Less code, more variations of code used or an alternative to the one I just coded with different code tasks. \$\endgroup\$ – gerry7man555 Sep 5 '15 at 22:35
  • 1
    \$\begingroup\$ You need to check for boundary conditions. What if a = 0? What if the roots aren't real? What if they're equal? \$\endgroup\$ – saulspatz Sep 5 '15 at 23:03
  • 1
    \$\begingroup\$ Never edit code in question. \$\endgroup\$ – Caridorc Sep 6 '15 at 14:17
  • 1
    \$\begingroup\$ For further review ask a follow up \$\endgroup\$ – Caridorc Sep 6 '15 at 14:18
15
\$\begingroup\$

Repeating code infinitely

Right now, in order to have QuadSolver repeat forever, you're calling it recursively, by calling QuadSolver again inside of itself. Unlike functional languages, which are optimized for tail-call recursion, Python isn't. Once you've recursed in the same function 1000 times, Python will raise an error. You can technically set the recursion limit using sys.setrecursionlimit, but this is a very "hacky" way to do things.

The proper way to make any piece of code repeat for a variable amount is to use a while loop. This means that the body of your QuadSolver function should be wrapped in a while loop, like this:

def QuadSolver():
    while True:
        # Original code goes here.

By doing this your code gains a few good things:

  1. It will properly execute forever.
  2. It's faster.
  3. It's more readable, e.g, it's clear to the reader that you're executing a chunk of code forever.

Integer input validation

Never trust the user to enter the correct input. For example, what if I ran your program and entered asghiopisdfiojgpfdj for the variable a? Your program would raise a ValueError and crash. You need to use a try/except block to catch a ValueError in case the user enters the wrong input. This means that this section of code here:

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? ---> "))

Should be wrapped in a try/except block, like this:

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.")

Now, if a user enters incorrect input, the program will alert them to this, and start over.


Proper string formatting

The % operator is deprecated as of Python 2.6. Instead, you should be using the str.format function instead. For example, this line:

print("         X=%d  OR  X=%d ") % (X, X2)

Would become this:

print("         X={x1}  OR  X={x2}".format(x1=X, x2=X2))

str.format supports the following styles:

  1. Normal parameters:

    "{} {}".format("Hello", "world")
    
  2. Positional parameters:

    "{1} {0}".format("world", "Hello")
    
  3. Named parameters:

    "{word1} {word2}".format(word1="Hello", word2="world")
    

You can do a great deal more with str.format, but I'll leave it up to you to figure that out, as there's too much for this one post.


Getting rid of the system calls

I find all of these lines of code to be absolutely horrid:

os.system('cls')
os.system('')
os.system('color a')
os.system('title Quadratic Equation Solver')
os.system('pause >nul')

Especially this one in particular:

os.system('pause >nul')

There are many things wrong here. For starters, the call to os.system has a long startup and "cooldown" period, e.g, it takes a fair amount of time. Secondly, all the commands you're running, like cls, color, or pause are very Windows-specific. What happens if someone wants to run this on a Linux-based system? Most of these system calls are purely stylistic, and unnecessary anyways.

On the matter of this line:

os.system('pause >nul')

I find it awful that bad C++ practices are leaking into Python. The method above is slow, insecure, and unreadable. If you want to pause until user input, just use the standard input operations of your language. In the case of Python, that would just look like this:

input()

If you're still using Python 2.x for some reason, it would look like this:

raw_input()

Proper style

Unlike many languages, Python has an official style guide, PEP8, and you're violating a fair amount of the guidelines set there.

  • Variable names should be in snake_case, and UPPER_SNAKE_CASE if they're constants.
  • Function names should only be in snake_case.
  • Classes should be in PascalCase.
  • You should have two spaces between top-level code/functions/classes.

While the following items aren't actually in PEP8, they're kind of a code smell, and should be removed.

  • Separator comments, like the one below this should be removed. They're useless and look bad in your code.

    #------------------------------------------------
    
  • Inline comments on the end of code lines should be removed. If you're having to put comments on the end of lines of code, then you probably aren't writing the code in a clear enough way. If you feel the need to put comments at the end of lines of code, then chances are, those lines should be re-written.

It's also worth mentioning docstrings as well. Docstrings are a convenient way to describe your functions and classes in Python, much like XML documentation in Visual Studio. A typical function docstring generally looks something like this:

def my_function( ... ):
    """Brief description of the function.

    Detailed description of the function.

    argument_name -- Argument description.
    """

If we take this and apply it to your QuadSolver function, we get something like this:

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.
    """
    ...
\$\endgroup\$
  • \$\begingroup\$ Since you gave me alternatives for most of the os.system orders, what would be the equivalent of os.system('cls') ? Just wondering \$\endgroup\$ – gerry7man555 Sep 6 '15 at 1:33
  • \$\begingroup\$ @gerry7man555 The best you can get is using this ternary which will at the least, support windows, linux, and mac: os.system("cls" if os.name == "nt" else "clear") \$\endgroup\$ – Ethan Bierlein Sep 6 '15 at 1:36
8
\$\begingroup\$

I'm not a Pythonista, so I can't comment specifically on your use of Python. However, there's one language-independent issue which the existing answers don't mention. The algebraic solution of the quadratic equation is the textbook example of an issue in numerical analysis known as loss of signficance. The Wikipedia article on that topic goes into sufficient detail on this particular equation, but to summarise in case of link rot:

When b is much larger than a and c, sqrt(b*b - 4*a*c) is approximately equal to abs(b). That means that one of -b + sqrt(...) or -b - sqrt(...) will be subtracting two very similar numbers, and the result will only have a few bits of accuracy. The correct way to solve the quadratic equation in code is along the lines of

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
\$\endgroup\$
7
\$\begingroup\$

This is in no way a full answer, but I couldn't keep it to myself either.

print can handle newlines, so you don't need repeated print statements.

This:

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("")

Could be replaced for exact the same results by:

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")

Of-course, that's keeping the current way of writing pretty much intact.

If you prefer one-liners, this does exactly the same:

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")

However, this would violate the maximum line length noted in PEP8. Whether or not this is a problem is up to you.

\$\endgroup\$
  • \$\begingroup\$ Why not use multi-line strings with """? \$\endgroup\$ – sebix Sep 6 '15 at 15:41
  • 1
    \$\begingroup\$ @sebix There are many ways of doing this. I assumed this was the easiest to understand for OP. Also, when I wrote this, it was still on Stack Overflow. SO answers differ a little from CR ones. \$\endgroup\$ – Mast Sep 6 '15 at 15:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.