Click here to Skip to main content
12,069,536 members (62,505 online)
Click here to Skip to main content

Stats

45.4K views
2K downloads
48 bookmarked
Posted

Three Methods for Root-finding in C#

, 26 Jun 2014 BSD
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 The BSD License

Share

About the Author

John D. Cook
Singular Value Consulting
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.

 


You may also be interested in...

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