Closed-Form Polynomial Roots

This documentation was generated with the assistance of AI. Please report any inaccuracies.

Polynomials of degree one, two, and three have exact, closed-form solutions for their roots — no iteration, no bracket, no convergence tolerance required. This package implements all three as FirstDegreePolynomialRootsEstimator, SecondDegreePolynomialRootsEstimator, and ThirdDegreePolynomialRootsEstimator in the com.irurueta.numerical.roots package. Unlike the general one-dimensional root finders elsewhere on this page, these are not grounded in Press et al., 2007 — their javadoc instead cites the Wikipedia Quadratic function and Cubic function articles, since the underlying formulas are standard classical algebra rather than material from Numerical Recipes.

Linear equations

For , the root is immediate:

FirstDegreePolynomialRootsEstimator implements exactly this.

Quadratic equations

The quadratic discriminant classifies a parabola’s roots as two crossings, one tangent point, or none; the cubic’s h classifies it as three crossings or one crossing plus an inflection

For , the discriminant both solves the equation and classifies its roots:

  • — two distinct real roots.

  • (within a small numerical tolerance) — one real double root.

  • — two complex conjugate roots, .

SecondDegreePolynomialRootsEstimator implements this directly, and exposes the classification itself via hasTwoDistinctRealRoots(), hasDoubleRoot(), and hasTwoComplexConjugateRoots() so callers can inspect the root structure before (or instead of) reading the actual root values.

Cubic equations

For , this package uses the same discriminant-driven case analysis as the Wikipedia cubic equation article. Three intermediate quantities are computed first:

and then, depending on their values:

  • — a single real root with multiplicity three:

  • — three distinct real roots, found via the trigonometric method:

  • — one real root and a complex-conjugate pair:

ThirdDegreePolynomialRootsEstimator implements this case analysis directly, and — mirroring the quadratic estimator — exposes hasThreeDistinctRealRoots(), hasMultipleRealRoot(), and hasOneRealRootAndTwoComplexConjugateRoots() for inspecting the root structure.

flowchart TD A["Coefficients a, b, c, d"] --> B["Compute f, g, h"] B --> C{"f, g, h all ~= 0?"} C -->|"yes"| D["Triple real root: x = -cuberoot(d/a)"] C -->|"no"| E{"h <= 0?"} E -->|"yes"| F["Three distinct real roots\n(trigonometric method)"] E -->|"no"| G["One real root, two complex conjugate roots\n(Cardano's formula)"]

Library implementation

All three classes extend PolynomialRootsEstimator, but — unlike Laguerre’s Method for Polynomial Roots — accept only real polynomial coefficients (as a double[] array, constant term first):

Class Polynomial Coefficient array

FirstDegreePolynomialRootsEstimator

[b, a]

SecondDegreePolynomialRootsEstimator

[c, b, a]

ThirdDegreePolynomialRootsEstimator

[d, c, b, a]

Each has a static isFirstDegree(double[]) / isSecondDegree(double[]) / isThirdDegree(double[]) helper to validate a coefficient array before constructing the estimator. After estimate() completes, the inherited getRoots() returns a Complex[] — always length 1, 2, or 3 respectively, with real roots represented as a Complex with zero imaginary part, sorted by real part ascending.

For polynomials of degree four and above, no such closed form exists in general (a well-known result of Galois theory for degree five and up); see Laguerre’s Method for Polynomial Roots for this package’s general, iterative alternative.

Example

// x^2 - 4 = 0, coefficients [c, b, a] = [-4, 0, 1]
final var estimator = new SecondDegreePolynomialRootsEstimator(new double[]{-4.0, 0.0, 1.0});
estimator.estimate();

final var roots = estimator.getRoots(); // Complex[]{-2+0i, 2+0i}
final var hasTwoRealRoots = estimator.hasTwoDistinctRealRoots(); // true