Quadratic equation in Ada
Given ax2 + bx + c = 0 the quadradic formula gives solutions for x = (-b +/- sqrt(b2-4ac) ) / 2a. The discriminant d = b2-4ac will be positive for real valued roots, negative for roots with a non-zero imaginary component (i.e. a non-real complex number) and will be 0 when the root is a double root.
So, the Ada code for this would be:
D := B ** 2.0 - 4.0 * A * C;
IF D >= 0.0 THEN
X1 := (-B + Sqrt(D)) / (2.0 * A);
X2 := (-B - Sqrt(D)) / (2.0 * A);
ELSE
-- Deal with the fact that the result is a non-real complex number.
END IF;
Note: I'm a bit rusty in Ada, but this should be close to the proper syntax.
The quadratic formula is x = ( -b +/- sqrt ( b ** 2 - 4*a*c ) ) / ( 2 * a )
I'm guessing a is 1.
so x = -( b/2 ) +/- sqrt ( ( ( b ** 2 ) / 4 ) - c )
Calculate d = ( b ** 2 ) * 0.25 - c
then check its sign.
If the sign of d
is negative you have complex roots; handle them as you wish.
Replacing - c
with + abs ( c )
if b
happens to be negative will give you rubbish.
Usually multiplying by 0.5 or 0.25 is better than dividing by 2.0 or 4.0.
Solving quadratic equations is not as simple as most people think.
The standard formula for solving a x^2 + b x + c = 0
is
delta = b^2 - 4 a c
x1 = (-b + sqrt(delta)) / (2 a) (*)
x2 = (-b - sqrt(delta)) / (2 a)
but when 4 a c << b^2
, computing x1
involves subtracting close numbers, and makes you lose accuracy, so you use the following instead
delta as above
x1 = 2 c / (-b - sqrt(delta)) (**)
x2 = 2 c / (-b + sqrt(delta))
which yields a better x1, but whose x2 has the same problem as x1 had above.
The correct way to compute the roots is therefore
q = -0.5 (b + sign(b) sqrt(delta))
and use x1 = q / a
and x2 = c / q
, which I find very efficient. If you want to handle the case when delta
is negative, or complex coefficients, then you must use complex arithmetic (which is quite tricky to get right too).
Edit: With Ada code:
DELTA := B * B - 4.0 * A * C;
IF(B > 0.0) THEN
Q := -0.5 * (B + SQRT(DELTA));
ELSE
Q := -0.5 * (B - SQRT(DELTA));
END IF;
X1 := Q / A;
X2 := C / Q;