Skip to content

Instantly share code, notes, and snippets.

@jgphilpott
Last active November 19, 2022 10:22
Show Gist options
  • Save jgphilpott/e483b5fbe52a7233c292f35737e5a682 to your computer and use it in GitHub Desktop.
Save jgphilpott/e483b5fbe52a7233c292f35737e5a682 to your computer and use it in GitHub Desktop.
A collection of functions for finding the roots of polynomials in JavaScript.
findRoots = (y = 0, coefficients = []) ->
switch coefficients.length
when 0
return null
when 1
return uniFormula y, coefficients
when 2
return linierFormula y, coefficients
when 3
return quadraticFormula y, coefficients
when 4
return cubicFormula y, coefficients
when 5
return polyFormula y, coefficients
else
# Credit: https://math.stackexchange.com/a/200622/880755
return "No general formula exists for polynomials of degree ≥ 5, see Abel–Ruffini theorem: https://en.wikipedia.org/wiki/Abel%E2%80%93Ruffini_theorem"
uniFormula = (y = 0, coefficients = []) ->
if y == coefficients[0]
return Infinity
else
return null
linierFormula = (y = 0, coefficients = []) ->
return [(y - coefficients[0]) / coefficients[1]]
# Credit: https://stackoverflow.com/a/33454565/1544937
quadraticFormula = (y = 0, coefficients = []) ->
roots = []
a = coefficients[2]
b = coefficients[1]
c = coefficients[0] - y
positiveRoot = (-b + Math.sqrt(Math.pow(b, 2) - (4 * a * c))) / (2 * a)
negativeRoot = (-b - Math.sqrt(Math.pow(b, 2) - (4 * a * c))) / (2 * a)
if not isNaN positiveRoot then roots.push positiveRoot
if not isNaN negativeRoot then if negativeRoot != positiveRoot then roots.push negativeRoot
return roots
# Credit: https://stackoverflow.com/a/27176424/1544937
cubicFormula = (y = 0, coefficients = []) ->
roots = null
a = coefficients[3]
b = coefficients[2]
c = coefficients[1]
d = coefficients[0] - y
cuberoot = (x) ->
y = Math.pow(Math.abs(x), 1/3)
return if x < 0 then -y else y
if Math.abs(a) < 1e-8 # Quadratic case, ax^2 + bx + c = 0
a = b
b = c
c = d
if Math.abs(a) < 1e-8 # Linear case, ax + b = 0
a = b
b = c
if Math.abs(a) < 1e-8 # Degenerate case
return []
return [-b / a]
D = (b * b) - (4 * a * c)
if Math.abs(D) < 1e-8
return [-b / (2 * a)]
else if (D > 0)
return [(-b + Math.sqrt(D)) / (2 * a), (-b - Math.sqrt(D)) / (2 * a)]
return []
p = (3*a*c - b*b) / (3*a*a)
q = (2*b*b*b - 9*a*b*c + 27*a*a*d) / (27*a*a*a)
if Math.abs(p) < 1e-8
roots = [cuberoot(-q)]
else if Math.abs(q) < 1e-8
roots = [0].concat(if p < 0 then [Math.sqrt(-p), -Math.sqrt(-p)] else [])
else
D = q*q/4 + p*p*p/27
if Math.abs(D) < 1e-8
roots = [-1.5*q/p, 3*q/p]
else if D > 0
u = cuberoot(-q/2 - Math.sqrt(D))
roots = [u - p / (3*u)]
else
u = 2 * Math.sqrt(-p / 3)
t = Math.acos(3*q/p/u) / 3
k = 2 * Math.PI / 3
roots = [u * Math.cos(t), u * Math.cos(t-k), u * Math.cos(t-2*k)]
for root in roots
root -= b / (3*a)
return roots
# Credit: https://stackoverflow.com/q/27217113/1544937
polyFormula = (y = 0, coefficients = []) ->
return "https://en.wikipedia.org/wiki/Quartic_function"
// Generated by CoffeeScript 2.7.0
var cubicFormula, findRoots, linierFormula, polyFormula, quadraticFormula, uniFormula;
findRoots = function(y = 0, coefficients = []) {
switch (coefficients.length) {
case 0:
return null;
case 1:
return uniFormula(y, coefficients);
case 2:
return linierFormula(y, coefficients);
case 3:
return quadraticFormula(y, coefficients);
case 4:
return cubicFormula(y, coefficients);
case 5:
return polyFormula(y, coefficients);
default:
// Credit: https://math.stackexchange.com/a/200622/880755
return "No general formula exists for polynomials of degree ≥ 5, see Abel–Ruffini theorem: https://en.wikipedia.org/wiki/Abel%E2%80%93Ruffini_theorem";
}
};
uniFormula = function(y = 0, coefficients = []) {
if (y === coefficients[0]) {
return 2e308;
} else {
return null;
}
};
linierFormula = function(y = 0, coefficients = []) {
return [(y - coefficients[0]) / coefficients[1]];
};
// Credit: https://stackoverflow.com/a/33454565/1544937
quadraticFormula = function(y = 0, coefficients = []) {
var a, b, c, negativeRoot, positiveRoot, roots;
roots = [];
a = coefficients[2];
b = coefficients[1];
c = coefficients[0] - y;
positiveRoot = (-b + Math.sqrt(Math.pow(b, 2) - (4 * a * c))) / (2 * a);
negativeRoot = (-b - Math.sqrt(Math.pow(b, 2) - (4 * a * c))) / (2 * a);
if (!isNaN(positiveRoot)) {
roots.push(positiveRoot);
}
if (!isNaN(negativeRoot)) {
if (negativeRoot !== positiveRoot) {
roots.push(negativeRoot);
}
}
return roots;
};
// Credit: https://stackoverflow.com/a/27176424/1544937
cubicFormula = function(y = 0, coefficients = []) {
var D, a, b, c, cuberoot, d, i, k, len, p, q, root, roots, t, u;
roots = null;
a = coefficients[3];
b = coefficients[2];
c = coefficients[1];
d = coefficients[0] - y;
cuberoot = function(x) {
y = Math.pow(Math.abs(x), 1 / 3);
if (x < 0) {
return -y;
} else {
return y;
}
};
if (Math.abs(a) < 1e-8) { // Quadratic case, ax^2 + bx + c = 0
a = b;
b = c;
c = d;
if (Math.abs(a) < 1e-8) { // Linear case, ax + b = 0
a = b;
b = c;
if (Math.abs(a) < 1e-8) { // Degenerate case
return [];
}
return [-b / a];
}
D = (b * b) - (4 * a * c);
if (Math.abs(D) < 1e-8) {
return [-b / (2 * a)];
} else if (D > 0) {
return [(-b + Math.sqrt(D)) / (2 * a), (-b - Math.sqrt(D)) / (2 * a)];
}
return [];
}
p = (3 * a * c - b * b) / (3 * a * a);
q = (2 * b * b * b - 9 * a * b * c + 27 * a * a * d) / (27 * a * a * a);
if (Math.abs(p) < 1e-8) {
roots = [cuberoot(-q)];
} else if (Math.abs(q) < 1e-8) {
roots = [0].concat(p < 0 ? [Math.sqrt(-p), -Math.sqrt(-p)] : []);
} else {
D = q * q / 4 + p * p * p / 27;
if (Math.abs(D) < 1e-8) {
roots = [-1.5 * q / p, 3 * q / p];
} else if (D > 0) {
u = cuberoot(-q / 2 - Math.sqrt(D));
roots = [u - p / (3 * u)];
} else {
u = 2 * Math.sqrt(-p / 3);
t = Math.acos(3 * q / p / u) / 3;
k = 2 * Math.PI / 3;
roots = [u * Math.cos(t), u * Math.cos(t - k), u * Math.cos(t - 2 * k)];
}
}
for (i = 0, len = roots.length; i < len; i++) {
root = roots[i];
root -= b / (3 * a);
}
return roots;
};
// Credit: https://stackoverflow.com/q/27217113/1544937
polyFormula = function(y = 0, coefficients = []) {
return "https://en.wikipedia.org/wiki/Quartic_function";
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment