import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
/**
* Calculates the real roots of any polynomial using the rational roots theorem
* (has yet to implement rational roots perfectly, since it will not work unless at least one factor is an integer).
*
* @author Michael Yaworski of http://mikeyaworski.com
* @version July 2nd, 2015
*/
public class PolynomialRoots {
// index 0 starts at leading coefficient and last index is the constant
public static List<Double> getRoots(List<Double> coefficients) {
return getRoots(coefficients, new ArrayList<Double>());
}
public static List<Double> getRoots(List<Double> coefficients, List<Double> roots) {
if (coefficients.size() > 3) {
Double k = findK(coefficients);
if (k != null) {
roots.add(k);
coefficients = dividePolynomialByXMinusK(coefficients, k);
return getRoots(coefficients, roots);
}
} else if (coefficients.size() == 3) {
roots.addAll(getQuadraticRoots(coefficients.get(0), coefficients.get(1), coefficients.get(2)));
} else if (coefficients.size() == 2) {
roots.addAll(getQuadraticRoots(0, coefficients.get(0), coefficients.get(1)));
}
// sort the roots list
Collections.sort(roots, new Comparator<Double>() {
@Override
public int compare(Double d1, Double d2){
return d1.compareTo(d2);
}
});
// remove duplicates from the list
for (int i = 0; i < roots.size(); i++) {
if (roots.get(i).doubleValue() == 0) roots.set(i, new Double("0"));
for (int j = i + 1; j < roots.size(); j++) {
if (roots.get(i).doubleValue() == roots.get(j).doubleValue()) {
roots.remove(j);
j--;
}
}
}
return roots;
}
public static Double findK(List<Double> coefficients) {
if (coefficients.size() > 2) {
if (coefficients.get(coefficients.size() - 1) == 0) return 0d;
List<Double> trialKValues = new ArrayList<Double>();
Double constant = coefficients.get(coefficients.size() - 1);
Double leadingCoefficient = coefficients.get(0);
for (int i = 1; i <= Math.abs(constant); i++) {
if (Math.abs(constant) % i == 0) {
trialKValues.add((double)i);
trialKValues.add((double)i * -1);
for (int j = 1; j <= Math.abs(leadingCoefficient); j++) {
if (Math.abs(leadingCoefficient) % j == 0) {
if ((i/j) == ((double)i/j)) {
trialKValues.add(((double)i/j));
trialKValues.add(((double)i/j) * -1);
}
}
}
}
}
for (double k : trialKValues) {
double sumOfTerms = 0;
for (int i = 0; i < coefficients.size(); i++) { // f(x=k)
sumOfTerms += coefficients.get(i) * Math.pow(k, coefficients.size() - 1 - i);
}
if (sumOfTerms == 0) { // if f(x=k) == 0
return k;
}
}
}
return null;
}
public static List<Double> dividePolynomialByXMinusK(List<Double> coefficients, Double k) {
if (k != null && coefficients != null && coefficients.size() > 2) {
List<Double> newCoefficients = new ArrayList<Double>();
newCoefficients.add(coefficients.get(0));
for (int i = 1; i < coefficients.size() - 1; i++) {
newCoefficients.add(newCoefficients.get(i-1) * k + coefficients.get(i));
}
int lastIndex = coefficients.size() - 1;
if (newCoefficients.get(lastIndex-1) * k + coefficients.get(lastIndex) != 0) return null;
return newCoefficients;
}
return null;
}
public static List<Double> getQuadraticRoots(double a, double b, double c) {
List<Double> roots = new ArrayList<Double>();
if (a != 0) {
int nRoots = 0;
double discriminant = Math.pow(b, 2) - 4*a*c;
if (discriminant > 0) nRoots = 2;
else if (discriminant == 0) nRoots = 1;
if (nRoots == 1) {
roots.add(b * -1 / (2 * a));
} else if (nRoots == 2) {
roots.add(((b * -1 + Math.sqrt(discriminant)) / (2 * a)));
roots.add(((b * -1 - Math.sqrt(discriminant)) / (2 * a)));
}
} else {
roots.add(c * -1 / b);
}
return roots;
}
}
DOWNLOAD
Example of use:
List<Double> coefficients; // quartic coefficients = new ArrayList<Double>(); coefficients.add(1d); coefficients.add(8d); coefficients.add(4d); coefficients.add(-48d); coefficients.add(0d); System.out.println(Roots.getRoots(coefficients)); // [-6.0, -4.0, 0.0, 2.0] // cubic coefficients = new ArrayList<Double>(); coefficients.add(2d); coefficients.add(3d); coefficients.add(-17d); coefficients.add(-30d); System.out.println(Roots.getRoots(coefficients)); // [-2.5, -2.0, 3.0] // quadratic coefficients = new ArrayList<Double>(); coefficients.add(2d); coefficients.add(9d); coefficients.add(10d); System.out.println(Roots.getRoots(coefficients)); // [-2.5, -2.0] // linear coefficients = new ArrayList<Double>(); coefficients.add(9d); coefficients.add(10d); System.out.println(Roots.getRoots(coefficients)); // [-1.1111111111111112] // constant coefficients = new ArrayList<Double>(); coefficients.add(5d); System.out.println(Roots.getRoots(coefficients)); // []
Created: July 2, 2015
Completed in full by: Michael Yaworski