Solving the Quadratic Equation and Finite Precision

Let's go back to out quadratic equation solver:

In [1]:
import math

a = 2   
b = -20 
c = 1
disc = b**2-4*a*c

if disc > 0:
    r1 = (-b + math.sqrt(disc))/(2*a)
    r2 = (-b - math.sqrt(disc))/(2*a)
    print("Two roots:", r1, r2)
elif disc == 0:
    r = (-b + math.sqrt(disc))/(2*a)
    print("One root:", r)
else:
    print("There are no real solutions")
Two roots: 9.949747468305834 0.050252531694167324

In principle, we could expect that $ar_{1}^2 + br_{1} + c$ should be 0. Let's try this:

In [2]:
a*r1**2 + b*r1 + c
Out[2]:
2.842170943040401e-14

This is almost, but not quite, 0. That is because $r_1$ is irrational (it requires an infinite number in the mantissa to store exactly correctly). The variable r1 only approximates the true r_1 using about 17 decimal digits. That is one of the resons we are not getting exactly 0.

In general, because of the imprecision of floats, you should be wary every time there is a test to check whether a float is exactly equal to any number.

That makes the comparison disc == 0 suspect.

In some situations, it would make sense (for example, if we know that disc is definitely an integer.) In most situations, especially if the a, b, and c are physical measurements which were not taken with infinite precision, it makes no sense to think of the equation as having exactly one root, and the comparison disc == 0 doesn't really make sense.