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