Po-Shen Loh’s Quadratic Method

A quadratic equation is one that can be written as

y = ax2 + bx + c

Young math students are taught in an algebra course that they can compute the roots of a quadratic equation by using the quadratic formula, which is

x =
b ±
b2 − 4ac
2a

In 2019, Po-Shen Loh, a professor of mathematics at Carnegie Mellon University, published a new method for computing the roots of a quadratic equation. Loh’s method can be expressed with these two formulas:

V =
b
2a
x = −V ±
V2
 c 
a

After reading his paper, I decided to implement both the traditional quadratic formula and Loh’s new method in Python and compare them. Of course, both methods give the same results. As you can see from the code below, Loh’s method is slightly simpler and requires fewer computations.


import math

def main():
    tests = [
        (0, -3, 3),
        (1, -4, 4),
        (2, -6, 22.5),
        (2, -14, 24),
        (3, 0, -27),
        (0.5, 5, 12)
    ]
    for coeffs in tests:
        roots = quadratic(*coeffs)
        print(roots)
        verify_roots(*coeffs, *roots)
        roots = poshenloh(*coeffs)
        print(roots)
        verify_roots(*coeffs, *roots)


def quadratic(a, b, c):
    """Compute and return the roots of a quadratic
    equation using the traditional quadratic formula.

    Parameters
        a, b, c: The coefficients of a
        quadratic equation in the form:
        y = ax**2 + bx + c
    Return: the roots of the quadratic equation in a tuple
    """
    r1 = None
    r2 = None
    if a == 0:
        r1 = -c / b
    else:
        discr = b * b - 4 * a * c
        b = -b
        denom = 2 * a
        if discr > 0:
            sq = math.sqrt(discr)
            r1 = (b - sq) / denom
            r2 = (b + sq) / denom
        elif discr == 0:
            r1 = b / denom
        else:
            sq = math.sqrt(-discr)
            real = b / denom
            imag = sq / denom
            r1 = complex(real, -imag)
            r2 = complex(real, imag)
    return (r1, r2)


def poshenloh(a, b, c):
    """Compute and return the roots of a quadratic
    equation using the method developed by Po-Shen
    Loh in 2019.

    Parameters
        a, b, c: The coefficients of a
        quadratic equation in the form:
        y = ax**2 + bx + c
    Return: the roots of the quadratic equation in a tuple
    """
    r1 = None
    r2 = None
    if a == 0:
        r1 = -c / b
    else:
        avg = -b / (2 * a)
        discr = avg * avg - c / a
        if discr > 0:
            u = math.sqrt(discr)
            r1 = avg - u
            r2 = avg + u
        elif discr == 0:
            r1 = avg
        else:
            u = math.sqrt(-discr)
            r1 = complex(avg, -u)
            r2 = complex(avg, u)
    return (r1, r2)


def verify_roots(a, b, c, r1, r2):
    verify_root(a, b, c, r1)
    verify_root(a, b, c, r2)


def verify_root(a, b, c, x):
    """Verify that x is a root of y = ax**2 + bx + c.
    In other words, verify that ax**2 + bx + c is zero.
    """
    if x:
        y = a * x**2 + b * x + c
        if abs(y) > 1e-9:
            print("Error: invalid root " + x)


if __name__ == "__main__":
    main()

To see that Loh’s method requires fewer computations, first count the number of arithmetic operators in the quadratic method at lines 36–42. Counting the call to the math.sqrt method at line 40 as one operator, the traditional quadratic formula requires 11 computations. Now count the number of arithmetic operators in the poshenloh method at lines 70–75. Counting in the same way as we counted for the quadratic method, Loh’s method requires 9 computations, which is fewer than the 11 required by the traditional quadratic formula.