Skip to article frontmatterSkip to article content

Improved Quadratic Equation Solver

City University of Hong Kong
import math
import numpy as np
from ipywidgets import interact

In this notebook, we will improve the quadratic equation solver in the previous lab using conditional executions.

Discriminant

Recall that a quadratic equation is

ax2+bx+c=0ax^2+bx+c=0

where aa, bb, and cc are real-valued coefficients, and xx is the unknown variable.

The discriminant Δ discriminates the roots

b±Δ2a\frac{-b\pm \sqrt{\Delta}}{2a}

of a quadratic equation:

For example, if (a,b,c)=(1,2,1)(a,b,c)=(1,-2,1), then

Δ=(2)24(11)=0\Delta = (-2)^2 - 4(1\cdot 1) = 0

and so the repeated root is

b2a=22=1.- \frac{b}{2a} = \frac{2}2 = 1.

(x1)2=x22x+1(x-1)^2 = x^2 - 2x + 1 as expected.

def iszero(v, a, b, c, *, rel_tol=1e-9):
    # YOUR CODE HERE
    raise NotImplementedError
# tests
assert not iszero(1e-8, 0, 2, 1)
assert iszero(1e-8, 1, 0, 1, rel_tol=1e-7)
assert not iszero(5e-9, 1, 2, 0)
# hidden tests
def get_roots(a, b, c, *, rel_tol=1e-9):
    d = b**2 - 4 * a * c    # discriminant
    if iszero(d, a, b, c, rel_tol=rel_tol):
    # YOUR CODE HERE
    raise NotImplementedError
    return roots
# tests
assert np.isclose(get_roots(1, 1, 0), (-1.0, 0.0)).all()
assert np.isclose(get_roots(1, 0, 0), 0.0).all()

YOUR ANSWER HERE

Linear equation

YOUR ANSWER HERE

Nevertheless, the quadratic equation remains valid:

bx+c=0,bx + c=0,

the root of which is x=cbx = -\frac{c}b.

def get_roots(a, b, c, *, rel_tol=1e-9):
    d = b**2 - 4 * a * c
    # YOUR CODE HERE
    raise NotImplementedError
    return roots
# tests
assert np.isclose(get_roots(1, 1, 0), (-1.0, 0.0)).all()
assert np.isclose(get_roots(1, 0, 0), 0.0).all()
assert np.isclose(get_roots(1, -2, 1), 1.0).all()
assert np.isclose(get_roots(0, -2, 1), 0.5).all()

Degenerate cases

What if a=b=0a=b=0? In this case, the equation becomes

c=0c = 0

which is always satisfied if c=0c=0 but never satisfied if c0c\neq 0.

def get_roots(a, b, c, *, rel_tol=1e-9):
    d = b**2 - 4 * a * c
    # YOUR CODE HERE
    raise NotImplementedError
    return roots
# tests
assert np.isclose(get_roots(1, 1, 0), (-1.0, 0.0)).all()
assert np.isclose(get_roots(1, 0, 0), 0.0).all()
assert np.isclose(get_roots(1, -2, 1), 1.0).all()
assert np.isclose(get_roots(0, -2, 1), 0.5).all()
assert np.isclose(get_roots(0, 0, 0), (-float('inf'), float('inf'))).all()
assert get_roots(0, 0, 1) is None

After you have complete the exercises, you can run your robust solver below:

# quadratic equations solver
@interact(a=(-10, 10, 1), b=(-10, 10, 1), c=(-10, 10, 1))
def quadratic_equation_solver(a=1, b=2, c=1):
    print("Root(s):", get_roots(a, b, c))