Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Three Methods for Root-finding in C#

, 26 Jun 2014 Public Domain
Three numerical algorithms for solving equations, each implemented in C#
RootFinding_src.zip
RootFindingDemo
RootFindingDemo.suo
Properties
RootFindingDemo.csproj.user
using System;

namespace DemoApplication
{
    class Demo
    {
        // Note that this function is increasing for x < 1 and decreasing for x > 1.
        static double f(double x)
        {
            return x*Math.Exp(-x);
        }

        // Derivative of f
        static double fprime(double x)
        {
            return (1.0 - x) * Math.Exp(-x);
        }

        static void Main(string[] args)
        {
            const double tolerance = 1e-7;
            double expected, computed, target;



            // Test root finder on range where f is increasing.
            // f(-1) = target, so -1 is the exact answer.
            target = -2.71828182845905;
            expected = -1.0;

            Console.WriteLine("Test root-finding on region where function is increasing.\n"); 

            computed = RootFinding.Bisect(new FunctionOfOneVariable(f), -4, 1, tolerance, target);
            PrintResults("Bisect", computed, expected);

            computed = RootFinding.Brent(new FunctionOfOneVariable(f), -4, 1, tolerance, target);
            PrintResults("Brent ", computed, expected);

            computed = RootFinding.Newton(new FunctionOfOneVariable(f), fprime, 0.0, tolerance, target);
            PrintResults("Newton", computed, expected);


            // Test root finder on range where f is decreasing.
            // f(5) = target, so 5 is the exact answer.
            target = 0.0336897349954273;
            expected = 5.0;

            Console.WriteLine("Test root-finding on region where function is increasing.\n");

            computed = RootFinding.Bisect(new FunctionOfOneVariable(f), 3, 7.1, tolerance, target);
            PrintResults("Bisect", computed, expected);

            computed = RootFinding.Brent(new FunctionOfOneVariable(f), 3, 7.1, tolerance, target);
            PrintResults("Brent ", computed, expected);

            computed = RootFinding.Newton(new FunctionOfOneVariable(f), fprime, 4.0, tolerance, target);
            PrintResults("Newton", computed, expected);


            // Demonstrate validation.
            Console.WriteLine("");
            try
            {
                // There is no solution in the interval since f(3) and f(7) are both positive.
                // This should raise an exception.
                double x = RootFinding.Brent(new FunctionOfOneVariable(f), 3, 7, tolerance, 0.0);
                Console.WriteLine("WARNING: Missing validation logic. Should not have gotten here.");
            }
            catch(ArgumentException e)
            {
                Console.WriteLine("Correctly threw an exception when given bad input.");
                Console.WriteLine(e.Message);
            }

            Console.WriteLine();

            // Demonstrate efficiency of each method.
            int iterationsUsed;
            double errorEstimate;

            // Solve f(x) = 0.2 to 10 decimal places
            RootFinding.Bisect(new FunctionOfOneVariable(f), 1.0, 5.0, 1e-10, 0.2, out iterationsUsed, out errorEstimate);
            PrintEfficiencyAndAccuracy("Bisect", iterationsUsed, errorEstimate);
            RootFinding.Brent(new FunctionOfOneVariable(f), 1.0, 5.0, 1e-10, 0.2, out iterationsUsed, out errorEstimate);
            PrintEfficiencyAndAccuracy("Brent ", iterationsUsed, errorEstimate);
            RootFinding.Newton(new FunctionOfOneVariable(f), fprime, 2.0, 1e-10, 0.2, out iterationsUsed, out errorEstimate);
            PrintEfficiencyAndAccuracy("Newton", iterationsUsed, errorEstimate);
        }

        static void PrintResults(string method, double computed, double expected)
        {
            Console.WriteLine("Method:   {0}\nexpected: {1}\ncomputed: {2}\nerror:    {3}\n", method, expected, computed, Math.Abs(expected - computed));
        }

        static void PrintEfficiencyAndAccuracy(string method, int iterations, double error)
        {
            Console.WriteLine("Method:   {0}\niterations: {1}\nerror:     {2}\n", method, iterations, error);
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under A Public Domain dedication

Share

About the Author

John D. Cook

United States United States
I am an independent consultant in software development and applied mathematics. I help companies learn from their data to make better decisions.
 
Check out my blog or send me a note.
 

 

Follow on   Twitter   Google+

| Advertise | Privacy | Mobile
Web03 | 2.8.141022.1 | Last Updated 26 Jun 2014
Article Copyright 2010 by John D. Cook
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid