Solving cubic polynomials
There are many sources for how to solve cubic polynomials, often with many peripheral details, so a summarised and simplfied version is helpful when implementing a new code. This page is an attempt to record that.
We will consider the monic cubic polynomial in <math>x</math>, with <math>a</math>, <math>b</math> and <math>c</math> real-valued:
- <math> x^3 + a x^2 + b x + c = 0 </math>
To solve for <math>x</math>, we first calculate the coefficients of an equivalent 'depressed cubic' <math>y^3 + 3P y - 2Q = 0</math>, by substituting <math>x = y - a/3</math>:
- <math>3P = b - \frac{a^2}{3}</math>
- <math>2Q = \frac{2}{27} a^3 - \frac{1}{3} ab + c</math>
If <math>P</math> and <math>Q</math> are both zero, then we can stop here with a triple root <math>y = 0</math>, that is, <math>x = -\frac{a}{3}</math>.
If only <math>P</math> is zero, then <math>y^3 = 2Q</math>, so <math>x = \sqrt[3]{2Q}-\frac{a}{3}</math>.
If only <math>Q</math> is zero, the depressed cubic is simply <math>y^3+3Py = y \left(y^2 + 3P \right) = 0</math>, which has a real root at <math>y=0</math> and two more at <math>y = \pm \sqrt{-3P}</math>, which may be either real or imaginary, depending on the sign of <math>P</math>.
Otherwise, the depressed cubic can then be converted into a quadratic in <math>z^3</math> via the 'magic' Vieta substitution <math>y = z - \frac{P}{z}</math>,
- <math>\left(z^3\right)^2 - 2Q \left(z^3\right) - P^3 = 0</math>
for which the solution is
- <math>z^3 = Q \pm \sqrt{Q^2 + P^3}</math>
The original polynomal here has real coefficients, which means that any complex roots must appear with their complex conjugate. As such, the equation cannot have three imaginary roots (it can only have either zero or two imaginary roots), and therefore must have either one or three real roots.
This equation must be solved in general in the complex domain. The expression <math>\Delta = P^3 + Q^2</math>, the determinant, determines what kind of roots arise, noting that the original polynomial is assumed to have real coefficients.
is negative, then the right-hand side is immediately complex.
Three complex roots of <math>z^3 = r~\mathrm{cis}~\theta = r \cos \theta + i r \sin \theta</math> are calculated in general as
- <math> \sqrt[3]{z} = \sqrt[3]{r} \mathrm{cis}~\left(\frac{\theta}{n} + \frac{2\pi}{n} k \right)</math> for <math>k \in \left\lbrace 1,2,...,n-1 \right\rbrace</math>
Calculation checking
The following sympy code can be used to confirm the above results:
Invalid language.
You need to specify a language like this: <source lang="html">...</source>
Supported languages for syntax highlighting:
a4c, abap, abc, abnf, actionscript, ada, agda, alan, algol, ampl, amtrix, applescript, arc, arm, as400cl, ascend, asciidoc, asp, aspect, assembler, ats, autohotkey, autoit, avenue, awk, ballerina, bat, bbcode, bcpl, bibtex, biferno, bison, blitzbasic, bms, bnf, boo, c, carbon, ceylon, charmm, chill, chpl, clean, clearbasic, clipper, clojure, clp, cmake, cobol, coffeescript, coldfusion, conf, cpp2, critic, crk, crystal, cs_block_regex, csharp, css, d, dart, delphi, diff, dockerfile, dts, dylan, ebnf, ebnf2, eiffel, elixir, elm, email, erb, erlang, euphoria, exapunks, excel, express, factor, fame, fasm, felix, fish, fortran77, fortran90, frink, fsharp, fstab, fx, gambas, gdb, gdscript, go, graphviz, haml, hare, haskell, haxe, hcl, html, httpd, hugo, icon, idl, idlang, inc_luatex, informix, ini, innosetup, interlis, io, jam, jasmin, java, javascript, js_regex, json, jsp, jsx, julia, kotlin, ldif, less, lhs, lilypond, limbo, lindenscript, lisp, logtalk, lotos, lotus, lua, luban, makefile, maple, markdown, matlab, maya, mercury, meson, miranda, mod2, mod3, modelica, moon, ms, msl, mssql, mxml, n3, nasal, nbc, nemerle, netrexx, nginx, nice, nim, nix, nsis, nxc, oberon, objc, ocaml, octave, oorexx, org, os, oz, paradox, pas, pdf, perl, php, pike, pl1, plperl, plpython, pltcl, po, polygen, pony, pov, powershell, pro, progress, ps, psl, pure, purebasic, purescript, pyrex, python, q, qmake, qml, qu, r, rebol, rego, rexx, rnc, rpg, rpl, rst, ruby, rust, s, sam, sas, scad, scala, scilab, scss, shellscript, slim, small, smalltalk, sml, snmp, snobol, solidity, spec, spn, sql, squirrel, styl, svg, swift, sybase, tcl, tcsh, terraform, tex, toml, tsql, tsx, ttcn3, txt, typescript, upc, vala, vb, verilog, vhd, vimscript, vue, wat, whiley, wren, xml, xpp, yaiff, yaml, yaml_ansible, yang, zig, znn