There are two situations where problems arise. The first is when the term inside the square root (the "Discriminant") goes negative, i.e.
if(b*b - 4*a*c < 0 ):
# do something. This doesn't have real roots
The second is more subtle. When you subtract two large numbers that are almost the same size, there is a possibility of rounding error. This will happen for the smaller root when 4*a*c << b*b
. You could do a series expansion:
b - sqrt(b*b - 4*a*c)
= b * ( 1 - sqrt(1 - 4 * a * c / (b * b)))
~ b * ( 1 - 1 + 2 * a * c / (b * b)) # when 4*a*c << b*b
This term becomes
2 * a * c / b
So the final root would be
x1 = - c / b
Which is an interesting result. Of course the other root is still
x2 = (b + sqrt( b * b - 4 * a * c)) / (2 * a)
Not much error propagation there - although you could say that it will tend to
x2 = - b / a
when c becomes very small.
All this has nothing to do with Python - it is basic math. And I may have made errors - go ahead and see if you can find them.
For more help you might want to look at http://en.wikipedia.org/wiki/Quadratic_equation#Floating-point_implementation
Which provides a treatment of this issue in terms of numerical stability. You will find, among others, that the equations I (re)derived above are called "Vieta's formula".