Search code examples
javamathequationpolynomial-mathequation-solving

Solving polynomial equation in Java


I have the following code which gives the price given a certain rate:

public static void main(String[] args) {
    double term = 5;
    double coupon = 5;
    double rate = 0.0432;

    //should get the price == 103;
    double price;

    double sum = 0;
    for (int i = 1; i <= term; i++) {
        sum = sum + (coupon / Math.pow((1 + rate), i));
    }

    double lastAmount = (100 / Math.pow((1 + rate), (term)));

    price = sum + lastAmount;

    System.out.println("price is:" + price);
}

My question is, how can I do this other way around? where the price is given and the rate is unknown. So I figured out, it's going to be an exponential equation. where it should look like below:

103x^5 - 5x^4 - 5x^3 - 5x^2 - 5x - 105=0

where x = 1+rate

solving the exponential equation, you get x = 1.0432 which means the rate is 0.0432 as expected.

How can I implement this in java to solve the equation.


Solution

  • Here is code that does it using the implementation of Brent's Method for root finding (from Apache Commons). It will print any roots between -10000 and +10000. It may not work for functions having multiple roots less than intervalSize (0.01) apart (yours is not such a function).

    package sandbox;
    
    import org.apache.commons.math3.analysis.UnivariateFunction;
    import org.apache.commons.math3.analysis.solvers.BrentSolver;
    
    public class BrentsMethodRootFinderExample {
    
        private void solveit () {
            BrentSolver solver = new BrentSolver();
            UnivariateFunction f = new UnivariateFunction() {
    
                @Override
                public double value(double x) {
                    return 103*Math.pow(x, 5.0)-5*Math.pow(x, 4.0)-5*Math.pow(x, 3.0)-5*Math.pow(x, 2.0)-5*x - 105;
                }
            };
    
            double intervalStart = -10000;
            double intervalSize = 0.01;
            while (intervalStart < 10000) {
                intervalStart+= intervalSize;
                if(Math.signum(f.value(intervalStart)) != Math.signum(f.value(intervalStart+intervalSize))) {
                    System.out.println("x = " + solver.solve(1000, f, intervalStart, intervalStart+intervalSize));
                }
            }
        }
    
        public static void main(String[] args) {
            new BrentsMethodRootFinderExample().solveit();
        }
    
    
    }
    

    Output:

    x = 1.0432004413216969