C#,数值计算——用于积分的梯形法(Trapezoidal Rule)的计算方法与源程序

1 文本格式

using System;

namespace Legalsoft.Truffer
{
    /// <summary>
    /// Routine implementing the extended trapezoidal rule.
    /// </summary>
    public class Trapzd : Quadrature
    {
        /// <summary>
        /// Limits of integration and current value of integral.
        /// </summary>
        private double a { get; set; } = 0.0;
        private double b { get; set; } = 0.0;
        private double s { get; set; } = 0.0;

        private UniVarRealValueFun funx;

        public Trapzd()
        {
        }

        /// <summary>
        /// The constructor takes as inputs func, the function or functor to be
        /// integrated between limits a and b, also input.
        /// </summary>
        /// <param name="funcc"></param>
        /// <param name="aa"></param>
        /// <param name="bb"></param>
        public Trapzd(UniVarRealValueFun funcc, double aa, double bb)
        {
            this.funx = funcc;
            this.a = aa;
            this.b = bb;
            n = 0;
        }

        /// <summary>
        /// Returns the nth stage of refinement of the extended trapezoidal rule.On
        /// the first call(n= 1),the routine returns the crudest estimate of S(a, b)f(x)dx.
        /// Subsequent calls set n=2,3,... and improve the accuracy by adding 2n-2
        /// additional interior points.
        /// </summary>
        /// <returns></returns>
        public override double next()
        {
            n++;
            if (n == 1)
            {
                return (s = 0.5 * (b - a) * (funx.funk(a) + funx.funk(b)));
            }
            else
            {
                int it = 1;
                for (int j = 1; j < n - 1; j++)
                {
                    it <<= 1;
                }
                double tnm = it;
                double del = (b - a) / tnm;
                double x = a + 0.5 * del;
                double sum = 0.0;
                for (int j = 0; j < it; j++, x += del)
                {
                    sum += funx.funk(x);
                }
                s = 0.5 * (s + (b - a) * sum / tnm);
                return s;
            }
        }

        /// <summary>
        /// Returns the integral of the function or functor func from a to b.The
        /// constants EPS can be set to the desired fractional accuracy and JMAX so
        /// that 2 to the power JMAX-1 is the maximum allowed number of steps.
        /// Integration is performed by the trapezoidal rule.
        /// </summary>
        /// <param name="funcc"></param>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="eps"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static double qtrap(UniVarRealValueFun funcc, double a, double b, double eps = 1.0e-10)
        {
            const int JMAX = 20;
            double s;
            double olds = 0.0;

            Trapzd t = new Trapzd(funcc, a, b);
            for (int j = 0; j < JMAX; j++)
            {
                s = t.next();
                if (j > 5)
                {
                    //if (Math.Abs(s - olds) < eps * Math.Abs(olds) || (s == 0.0 && olds == 0.0))
                    if (Math.Abs(s - olds) < eps * Math.Abs(olds) ||
                        (Math.Abs(s) <= float.Epsilon && Math.Abs(olds) <= float.Epsilon)
                    )
                    {
                        return s;
                    }
                }
                olds = s;
            }
            throw new Exception("Too many steps in routine qtrap");
        }

        /// <summary>
        /// Returns the integral of the function or functor func from a to b.The
        /// constants EPS can be set to the desired fractional accuracy and JMAX so
        /// that 2 to the power JMAX-1 is the maximum allowed number of steps.
        /// Integration is performed by Simpson's rule.
        /// </summary>
        /// <param name="funcc"></param>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="eps"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static double qsimp(UniVarRealValueFun funcc, double a, double b, double eps = 1.0e-10)
        {
            const int JMAX = 20;

            double ost = 0.0;
            double os = 0.0;
            Trapzd t = new Trapzd(funcc, a, b);
            for (int j = 0; j < JMAX; j++)
            {
                double st = t.next();
                double s = (4.0 * st - ost) / 3.0;
                if (j > 5)
                {
                    //if (Math.Abs(s - os) < eps * Math.Abs(os) || (s == 0.0 && os == 0.0))
                    if (Math.Abs(s - os) < eps * Math.Abs(os) || (Math.Abs(s) <= float.Epsilon && Math.Abs(os) <= float.Epsilon))
                    {
                        return s;
                    }
                }
                os = s;
                ost = st;
            }
            throw new Exception("Too many steps in routine qsimp");
        }


        public static double qromb(UniVarRealValueFun func, double a, double b)
        {
            return qromb(func, a, b, 1.0e-10);
        }


        /// <summary>
        /// Returns the integral of the function or functor func from a to b.
        /// Integration is performed by Romberg's method of order 2K, where, e.g., 
        /// K=2 is Simpson's rule.
        /// </summary>
        /// <param name="funcc"></param>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="eps"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static double qromb(UniVarRealValueFun funcc, double a, double b, double eps)
        {
            int JMAX = 20;
            int JMAXP = JMAX + 1;
            int K = 5;

            double[] s = new double[JMAX];
            double[] h = new double[JMAXP];
            Poly_interp polint = new Poly_interp(h, s, K);
            h[0] = 1.0;
            Trapzd t = new Trapzd(funcc, a, b);
            for (int j = 1; j <= JMAX; j++)
            {
                s[j - 1] = t.next();
                if (j >= K)
                {
                    double ss = polint.rawinterp(j - K, 0.0);
                    if (Math.Abs(polint.dy) <= eps * Math.Abs(ss)) return ss;
                }
                h[j] = 0.25 * h[j - 1];
            }
            throw new Exception("Too many steps in routine qromb");
        }
    }
}

2 代码格式

using System;

namespace Legalsoft.Truffer
{
    /// <summary>
    /// Routine implementing the extended trapezoidal rule.
    /// </summary>
    public class Trapzd : Quadrature
    {
        /// <summary>
        /// Limits of integration and current value of integral.
        /// </summary>
        private double a { get; set; } = 0.0;
        private double b { get; set; } = 0.0;
        private double s { get; set; } = 0.0;

        private UniVarRealValueFun funx;

        public Trapzd()
        {
        }

        /// <summary>
        /// The constructor takes as inputs func, the function or functor to be
        /// integrated between limits a and b, also input.
        /// </summary>
        /// <param name="funcc"></param>
        /// <param name="aa"></param>
        /// <param name="bb"></param>
        public Trapzd(UniVarRealValueFun funcc, double aa, double bb)
        {
            this.funx = funcc;
            this.a = aa;
            this.b = bb;
            n = 0;
        }

        /// <summary>
        /// Returns the nth stage of refinement of the extended trapezoidal rule.On
        /// the first call(n= 1),the routine returns the crudest estimate of S(a, b)f(x)dx.
        /// Subsequent calls set n=2,3,... and improve the accuracy by adding 2n-2
        /// additional interior points.
        /// </summary>
        /// <returns></returns>
        public override double next()
        {
            n++;
            if (n == 1)
            {
                return (s = 0.5 * (b - a) * (funx.funk(a) + funx.funk(b)));
            }
            else
            {
                int it = 1;
                for (int j = 1; j < n - 1; j++)
                {
                    it <<= 1;
                }
                double tnm = it;
                double del = (b - a) / tnm;
                double x = a + 0.5 * del;
                double sum = 0.0;
                for (int j = 0; j < it; j++, x += del)
                {
                    sum += funx.funk(x);
                }
                s = 0.5 * (s + (b - a) * sum / tnm);
                return s;
            }
        }

        /// <summary>
        /// Returns the integral of the function or functor func from a to b.The
        /// constants EPS can be set to the desired fractional accuracy and JMAX so
        /// that 2 to the power JMAX-1 is the maximum allowed number of steps.
        /// Integration is performed by the trapezoidal rule.
        /// </summary>
        /// <param name="funcc"></param>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="eps"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static double qtrap(UniVarRealValueFun funcc, double a, double b, double eps = 1.0e-10)
        {
            const int JMAX = 20;
            double s;
            double olds = 0.0;

            Trapzd t = new Trapzd(funcc, a, b);
            for (int j = 0; j < JMAX; j++)
            {
                s = t.next();
                if (j > 5)
                {
                    //if (Math.Abs(s - olds) < eps * Math.Abs(olds) || (s == 0.0 && olds == 0.0))
                    if (Math.Abs(s - olds) < eps * Math.Abs(olds) ||
                        (Math.Abs(s) <= float.Epsilon && Math.Abs(olds) <= float.Epsilon)
                    )
                    {
                        return s;
                    }
                }
                olds = s;
            }
            throw new Exception("Too many steps in routine qtrap");
        }

        /// <summary>
        /// Returns the integral of the function or functor func from a to b.The
        /// constants EPS can be set to the desired fractional accuracy and JMAX so
        /// that 2 to the power JMAX-1 is the maximum allowed number of steps.
        /// Integration is performed by Simpson's rule.
        /// </summary>
        /// <param name="funcc"></param>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="eps"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static double qsimp(UniVarRealValueFun funcc, double a, double b, double eps = 1.0e-10)
        {
            const int JMAX = 20;

            double ost = 0.0;
            double os = 0.0;
            Trapzd t = new Trapzd(funcc, a, b);
            for (int j = 0; j < JMAX; j++)
            {
                double st = t.next();
                double s = (4.0 * st - ost) / 3.0;
                if (j > 5)
                {
                    //if (Math.Abs(s - os) < eps * Math.Abs(os) || (s == 0.0 && os == 0.0))
                    if (Math.Abs(s - os) < eps * Math.Abs(os) || (Math.Abs(s) <= float.Epsilon && Math.Abs(os) <= float.Epsilon))
                    {
                        return s;
                    }
                }
                os = s;
                ost = st;
            }
            throw new Exception("Too many steps in routine qsimp");
        }


        public static double qromb(UniVarRealValueFun func, double a, double b)
        {
            return qromb(func, a, b, 1.0e-10);
        }


        /// <summary>
        /// Returns the integral of the function or functor func from a to b.
        /// Integration is performed by Romberg's method of order 2K, where, e.g., 
        /// K=2 is Simpson's rule.
        /// </summary>
        /// <param name="funcc"></param>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="eps"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static double qromb(UniVarRealValueFun funcc, double a, double b, double eps)
        {
            int JMAX = 20;
            int JMAXP = JMAX + 1;
            int K = 5;

            double[] s = new double[JMAX];
            double[] h = new double[JMAXP];
            Poly_interp polint = new Poly_interp(h, s, K);
            h[0] = 1.0;
            Trapzd t = new Trapzd(funcc, a, b);
            for (int j = 1; j <= JMAX; j++)
            {
                s[j - 1] = t.next();
                if (j >= K)
                {
                    double ss = polint.rawinterp(j - K, 0.0);
                    if (Math.Abs(polint.dy) <= eps * Math.Abs(ss)) return ss;
                }
                h[j] = 0.25 * h[j - 1];
            }
            throw new Exception("Too many steps in routine qromb");
        }
    }
}

猜你喜欢

转载自blog.csdn.net/beijinghorn/article/details/132747302
今日推荐