Although a closed form solution exists for the roots of polynomials of degree ≤ 4, the general formulae for cubics (and quartics) is ugly.
Various simplifications can be made; commonly, the cubic a3x3+a2x2+a1x+a0 is transformed by substituting x=t−a2/3a3, giving
Several strategies exist for solving this depressed cubic, but most involve dealing with complex numbers, even when we only want to find real roots.
Fortunately, there are a couple ways to find solutions with only real arithmetic. First, we need to know the value of the discriminant Δ=4p3+27q2.
If Δ<0, then there are three real roots; this is the tough case.
Luckily, we can use the uncommon trigonometric identity 4cos3(θ)−3cos(θ)−cos(3θ)=0 to calculate the roots with trig functions.
Making another substitution, t=2−p/3cos(θ), gives us
4cos3(θ)−3cos(θ)−2p3qp−3=0,
so
cos(3θ)=2p3qp−3.
Thus the three roots are:
tn=23−pcos(31cos−1(2p3qp−3)−32πn),
for n∈{0,1,2}.
We can save a cosine calculation by noting that t2=−t0∣q=−q and t1=−(t0+t2).
When generated in this way, the roots are ordered from smallest to largest (t0<t1<t2).
For the Δ>0 case, there is a single real root.
We can apply the general cubic formula and avoid dealing with complex numbers, provided we choose the signs right.
In this case,
t=−sgn(q)(C−3Cp), where C=3108Δ+2∣q∣.
When Δ=0, there is a root of at least multiplicity 2, and we can avoid calculating any radicals.
If p=0, the only root is t0=0; otherwise, the duplicate root is −3q/2p and the simple root is 3q/p.
My C implementation of this solution method can be seen in the dmnsn_solve_cubic() function here.