27
$\begingroup$

I'd like to solve $ax^3 + bx^2 + cx + d = 0$ using the cubic formula.

I coded three versions of this formula, described in three sources: MathWorld, EqWorld,
and in the book, "The Unattainable Attempt to Avoid the Casus Irreducibilis for Cubic Equations".

While I get identical results across all versions, these results are incorrect.

For example, for $a=1$, $b=2$, $c=3$, $d=4$,

I find incorrect roots:
$x_1 = -0.1747 - 0.8521i$,
$x_2 = 0.4270 + 1.1995i$,
$x_3 = -2.2523 - 0.3474i$.

The correct roots are:
$x_1 = -1.6506$,
$x_2 = -0.1747 + 1.5469i$,
$x_3 = -0.1747 - 1.5469i$

In case you're interested, the actual code is below. Thank you for your help!

%% Wolfram version

Q = (3*c - b^2) / 9;
R = (9*b*c - 27*d - 2*b^3) / 54;

D = Q^3 + R^2;
S = (R + sqrt(D))^(1/3);
T = (R - sqrt(D))^(1/3);

x1 = - b/3 + (S + T);
x2 = - b/3 - (S + T) / 2 + sqrt(-3) * (S - T) / 2;
x3 = - b/3 - (S + T) / 2 - sqrt(-3) * (S - T) / 2;

%% Book version

omega1 = - 1/2 + sqrt(-3)/2;
omega2 = - 1/2 - sqrt(-3)/2;

p = (3*a*c - b^2) / (3*a^2);
q = (2*b^3 - 9*a*b*c + 27*(a^3)*d) / (27*a^3);

r = sqrt(q^2/4 + p^3/27);
s = (-q/2 + r)^(1/3);
t = (-q/2 - r)^(1/3);

x1 =        s +        t - b/(3*a);
x2 = omega1*s + omega2*t - b/(3*a);
x3 = omega2*s + omega1*t - b/(3*a);

%% Eqworld version

p = - 1/3  * (b/a)^2 + (c/a);
q =   2/27 * (b/a)^3 - (b*c)/(3*a^2) + d/a;

D = (p/3)^3 + (q/2)^2;
A = (-q/2 + sqrt(D))^(1/3);
B = (-q/2 - sqrt(D))^(1/3);

y1 = A + B;
y2 = - 1/2 * (A + B) + sqrt(-3)/2 * (A - B);
y3 = - 1/2 * (A + B) - sqrt(-3)/2 * (A - B);

x1 = y1 - b / (3*a);
x2 = y2 - b / (3*a);
x3 = y3 - b / (3*a);
$\endgroup$
5
  • $\begingroup$ I haven't looked into your solution carefully, but a common error in cases like this is to inadvertently use integer division instead of fractional division, which is an easy mistake in many programming systems. Is it possible that you've done this? Can you check omega1 and make sure the -1/2 didn't get dropped? $\endgroup$
    – MJD
    May 17, 2017 at 14:32
  • $\begingroup$ Thank you for your help.This part seems Ok (I'm using Matlab). $\endgroup$
    – Akim
    May 17, 2017 at 14:44
  • 4
    $\begingroup$ For purposes of numerical stability, you might be interested in this formulation. $\endgroup$ May 17, 2017 at 21:02
  • $\begingroup$ I think this is a great alternative; perhaps one downside is the need to compute trigonometric functions. $\endgroup$
    – Akim
    May 18, 2017 at 2:15
  • 1
    $\begingroup$ Akim, it's a tradeoff (which happens often in programming applications): in casus irreducibilis, you have the choice of either avoiding complex arithmetic and using trigonometry, or using only radicals and arithmetic, but won't be able to avoid complex evaluations. $\endgroup$ May 18, 2017 at 7:13

2 Answers 2

45
$\begingroup$

The problem occurs when you are taking a cube root: in the Wolfram version, when you compute $$T = \sqrt[3]{R - \sqrt{D}} = \sqrt[3]{-\frac{35}{27}-\sqrt{\frac{50}{27}}}$$ and in corresponding places in the other versions of the cubic formula.

The expression inside the cube root is negative (approximately $-2.66$), and the cubic formula works if you take the real cube root (approximately $-1.39$). But writing $(R - \sqrt D)^{1/3}$ in many computer algebra systems instead computes the principal cube root: the complex root with largest real part. This will be the real cube root for a positive number, but here, it gives us approximately $0.69 - 1.2 i$, and that is the source of your error.

I can't identify the language you're using by looking at it, so I don't know what the best way to avoid this problem is. In Mathematica, there's a built-in CubeRoot command, which will always take the real root of a real number.

You can always make it go with some conditionals: define $T$ to be

  • $(R - \sqrt{D})^{1/3}$, if $R - \sqrt D \ge 0$, and
  • $-(\sqrt D - R)^{1/3}$, if $R - \sqrt D < 0$.

(And do a similar thing everywhere else you take a cube root.)


The above will work for real coefficients; for complex coefficients (or even when $D$ is negative), we want to be more careful, because then a real root might not exist.

The idea is that we ran into trouble here, not because we weren't taking the real root necessarily, but because we took two cube roots that "didn't match up with each other". We can rewrite the cubic formula in a few different ways so that we only take one cube root, and express the other cube root we'd have to take in terms of the first. Then the issue doesn't occur.

This gives us a better way to solve the problem in code: after computing $S = (R + \sqrt D)^{1/3}$, set $T = -Q/S$. The justification is this: since $S^3 = R + \sqrt D$ and $T^3 = R - \sqrt D$, we have $S^3 T^3 = R^2 - D = -Q^3$. Naively, we can cancel the cube roots and assume $ST = -Q$, and this works out.

See also this question and its answer.

$\endgroup$
7
  • 1
    $\begingroup$ Thank you so much for this! I'm using Matlab but ultimately will convert the code to C. Let me check and see how I can fix it. $\endgroup$
    – Akim
    May 17, 2017 at 14:47
  • 2
    $\begingroup$ In Matlab, it seems like the nthroot command takes real roots, and C has the cbrt command. $\endgroup$ May 17, 2017 at 14:50
  • $\begingroup$ Thanks Misha! I will be able to test this properly in a couple of hours. $\endgroup$
    – Akim
    May 17, 2017 at 14:52
  • $\begingroup$ Good explanation. Wikipedia's solution in terms of the cycles of ${\zeta}^k$ is a little friendlier as well in this regard, because then it doesn't matter which cube root is chosen (so long as it is chosen consistently). $\endgroup$ May 17, 2017 at 15:13
  • 1
    $\begingroup$ I agree, it seems most straightforward to proceed with $ST = - Q$. It's interesting that this ambiguity is not mentioned in any of the original sources. $\endgroup$
    – Akim
    May 17, 2017 at 16:54
-2
$\begingroup$

This does not look right.

y2 = - 1/2 * (A + B) + sqrt(-3)/2 * (A - B);
y3 = - 1/2 * (A + B) - sqrt(-3)/2 * (A - B);

Did you mean cbrt(-3)?

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .