How can I solve for $x$ values of a cubic function where $x$ intersects a given $y$?

1.1k Views Asked by At

Given the cubic function: y = -3 + 10x - 7x^2 + 1x^3, how can I find a value of x when y = 0.5?

WolframAlpha shows 3 possible solutions when y = 0.5: 0.535, 1.256 and 5.209.

How did WolframAlpha calculate this?

Approximations are fine.

Ultimately I need to calculate this step by step in code, so showing your work is a huge help.

I'll be solving for x thousands of these with different coefficients and y values. In my particular case, y will always be between 0 and 1 and the only x I care about will also be between 0 and 1.

Plot

3

There are 3 best solutions below

0
On BEST ANSWER

User Izumi Kawashima at StackOverflow pointed me to EasyCalculation.com's JavaScript algorithm (below). This made my job super easy.

His question is to find an even faster algorithm, so if you can think of one, I'm sure he'd appreciate it.

Posted here for posterity.

function positiveCube(s){
  var d3 = 1 / 3.0;
  return (s < 0) ? -Math.pow(-s, d3) : Math.pow(s, d3);
}

var p = [2,3,4,5]; // f(x) = 2 + 3x + 4x^2 + 5x^3
var roots = [];    // found real roots will be pushed

var a = p[3];
var b = p[2] / a;
var c = p[1] / a;
var d = p[0] / a;
var b2 = b * b;
var q = (3.0 * c - b2) / 9.0;
var r = (-27.0 * d + b * (9.0 * c - 2.0 * b2)) / 54.0;
var q3 = q * q * q;
var discrim = q3 + r * r;
var term1 = b / 3.0;

if (discrim > 0) {
  // One real, two complex roots
  var s, t;
  var discrimsq = Math.sqrt(discrim);
  s = r + discrimsq;
  t = r - discrimsq;
  s = positiveCube(s);
  t = positiveCube(t);
  roots.push(-term1 + s + t);
}else if (discrim === 0) {
  // Three real, two of them equal
  var r13 = positiveCube(r);
  roots.push(-term1 + r13 * 2.0);
  roots.push(-r13 - term1);
  roots.sort();
}else {
  q = -q;
  q3 = -q3;
  var dum1 = Math.acos(r / Math.sqrt(q3));
  var r13 = 2.0 * Math.sqrt(q);
  roots.push(-term1 + r13 * Math.cos(dum1 / 3));
  roots.push(-term1 + r13 * Math.cos((dum1 + 2 * Math.PI) / 3));
  roots.push(-term1 + r13 * Math.cos((dum1 + 4 * Math.PI) / 3));
  roots.sort();
}
2
On

Instead of finding $x$ such that $-3 + 10x - 7x^2 + 1x^3 = 0.5$, it's more conventional to move the $0.5$ over and equivalently look for $x$ that satisfies $ -3.5 + 10x - 7x^2 + 1x^3 = 0$. This task is called finding the roots of a polynomial.

The only bulletproof way I know of is to use Sturm's theorem and use binary search to zoom in on the roots. But you can usually get away with binary search (if you know two bounds of the root with opposite sign under the polynomial) or Newton's method (if you know a point close to the root and the polynomial is well-behaved nearby.).

0
On

For sure, Cardano method is the general way to get the solutions (real or complex).

In the case where the equation has three real roots, you can also use the trigonometric method. In the case you posted, the solutions will then be given by $$x_1=\frac{7}{3}+\frac{2}{3} \sqrt{19} \cos \left(\theta\right)$$ $$x_2=\frac{7}{3}+\sqrt{\frac{19}{3}} \sin \left(\theta\right)-\frac{1}{3} \sqrt{19} \cos \left(\theta\right)$$ $$x_3=\frac{7}{3}-\sqrt{\frac{19}{3}} \sin \left(\theta\right)-\frac{1}{3} \sqrt{19} \cos \left(\theta\right)$$ using $$\theta=\frac{1}{3} \tan ^{-1}\left(\frac{3 \sqrt{2127}}{301}\right) $$which numerically are $$x_1\approx 5.20935\quad \,\quad x_2\approx1.25552\quad \,\quad x_3\approx0.535132$$

If only one real root exists, then it can be obtained using hyperbolic functions.

For the ordering of the roots when all are real, you could look at the comments to this question of mine.