当前位置:首页 > 编程笔记 > 正文
已解决

C#,数值计算——函数计算,切比雪夫近似算法(Chebyshev approximation)的计算方法与源程序

来自网友在路上 191891提问 提问时间:2023-11-09 08:38:39阅读次数: 91

最佳答案 问答题库918位专家为你答疑解惑

1 文本格式

using System;

namespace Legalsoft.Truffer
{
    /// <summary>
    /// Chebyshev approximation
    /// </summary>
    public class Chebyshev
    {
        private int n { get; set; }
        private int m { get; set; }
        private double[] c { get; set; }
        private double a { get; set; }
        private double b { get; set; }

        public Chebyshev(double[] cc, double aa, double bb)
        {
            this.n = cc.Length;
            this.m = n;
            this.c = Globals.CopyFrom(cc);
            this.a = aa;
            this.b = bb;
        }

        public Chebyshev(double[] d)
        {
            this.n = d.Length;
            this.m = n;
            this.c = new double[n];
            this.a = -1.0;
            this.b = 1.0;

            c[n - 1] = d[n - 1];
            c[n - 2] = 2.0 * d[n - 2];
            for (int j = n - 3; j >= 0; j--)
            {
                c[j] = 2.0 * d[j] + c[j + 2];
                for (int i = j + 1; i < n - 2; i++)
                {
                    c[i] = (c[i] + c[i + 2]) / 2;
                }
                c[n - 2] /= 2;
                c[n - 1] /= 2;
            }
        }
        /*
        public Chebyshev(UniVarRealValueFun func, double aa, double bb)
        {
            new this(func, aa, bb, 50);
        }
        */
        /// <summary>
        /// Inverse of routine polycofs in Chebyshev: Given an array of polynomial
        /// coefficients d[0..n - 1], construct an equivalent Chebyshev object.
        /// </summary>
        /// <param name="func"></param>
        /// <param name="aa"></param>
        /// <param name="bb"></param>
        /// <param name="nn"></param>
        public Chebyshev(UniVarRealValueFun func, double aa, double bb, int nn = 50)
        {
            this.n = nn;
            this.m = nn;
            this.c = new double[n];
            this.a = aa;
            this.b = bb;

            double[] f = new double[n];
            double bma = 0.5 * (b - a);
            double bpa = 0.5 * (b + a);
            for (int k = 0; k < n; k++)
            {
                double y = Math.Cos(Math.PI * (k + 0.5) / n);
                f[k] = func.funk(y * bma + bpa);
            }
            double fac = 2.0 / n;
            for (int j = 0; j < n; j++)
            {
                double sum = 0.0;
                for (int k = 0; k < n; k++)
                {
                    sum += f[k] * Math.Cos(Math.PI * j * (k + 0.5) / n);
                }
                c[j] = fac * sum;
            }
        }

        public double eval(double x, int m)
        {
            double d = 0.0;
            double dd = 0.0;

            if ((x - a) * (x - b) > 0.0)
            {
                throw new Exception("x not in range in Chebyshev::eval");
            }
            double y = (2.0 * x - a - b) / (b - a);
            double y2 = 2.0 * (y);
            for (int j = m - 1; j > 0; j--)
            {
                double sv = d;
                d = y2 * d - dd + c[j];
                dd = sv;
            }
            return y * d - dd + 0.5 * c[0];
        }

        public double[] getc()
        {
            return c;
        }

        /// <summary>
        /// Return a new Chebyshev object that approximates the derivative of the
        /// existing function over the same range[a, b].
        /// </summary>
        /// <returns></returns>
        public Chebyshev derivative()
        {
            double[] cder = new double[n];
            cder[n - 1] = 0.0;
            cder[n - 2] = 2 * (n - 1) * c[n - 1];
            for (int j = n - 2; j > 0; j--)
            {
                cder[j - 1] = cder[j + 1] + 2 * j * c[j];
            }
            double con = 2.0 / (b - a);
            for (int j = 0; j < n; j++)
            {
                cder[j] *= con;
            }
            return new Chebyshev(cder, a, b);
        }

        /// <summary>
        /// Return a new Chebyshev object that approximates the indefinite integral of
        /// the existing function over the same range[a, b]. The constant of
        /// integration is set so that the integral vanishes at a.
        /// </summary>
        /// <returns></returns>
        public Chebyshev integral()
        {
            double sum = 0.0;
            double fac = 1.0;
            double[] cint = new double[n];
            double con = 0.25 * (b - a);
            for (int j = 1; j < n - 1; j++)
            {
                cint[j] = con * (c[j - 1] - c[j + 1]) / j;
                sum += fac * cint[j];
                fac = -fac;
            }
            cint[n - 1] = con * c[n - 2] / (n - 1);
            sum += fac * cint[n - 1];
            cint[0] = 2.0 * sum;
            return new Chebyshev(cint, a, b);
        }

        /// <summary>
        /// Polynomial coefficients from a Chebyshev fit.Given a coefficient array
        /// c[0..n-1], this routine returns a coefficient array d[0..n-1] such that
        /// sum(k= 0, n-1)dky^k = sum(k= 0, n-1)Tk(y)-c0/2. The method is Clenshaw's
        /// recurrence(5.8.11), but now applied algebraically rather than arithmetically.
        /// </summary>
        /// <param name="m"></param>
        /// <returns></returns>
        public double[] polycofs(int m)
        {
            double[] d = new double[m];
            double[] dd = new double[m];
            for (int j = 0; j < m; j++)
            {
                d[j] = 0.0;
                dd[j] = 0.0;
            }
            d[0] = c[m - 1];
            for (int j = m - 2; j > 0; j--)
            {
                for (int k = m - j; k > 0; k--)
                {
                    double s1v = d[k];
                    d[k] = 2.0 * d[k - 1] - dd[k];
                    dd[k] = s1v;
                }
                double s2v = d[0];
                d[0] = -dd[0] + c[j];
                dd[0] = s2v;
            }
            for (int j = m - 1; j > 0; j--)
            {
                d[j] = d[j - 1] - dd[j];
            }
            d[0] = -dd[0] + 0.5 * c[0];
            return d;
        }

        public int setm(double thresh)
        {
            while (m > 1 && Math.Abs(c[m - 1]) < thresh)
            {
                m--;
            }
            return m;
        }

        public double get(double x)
        {
            return eval(x, m);
        }

        public double[] polycofs()
        {
            return polycofs(m);
        }

        public static void pcshft(double a, double b, double[] d)
        {
            int n = d.Length;
            double cnst = 2.0 / (b - a);
            double fac = cnst;
            for (int j = 1; j < n; j++)
            {
                d[j] *= fac;
                fac *= cnst;
            }
            cnst = 0.5 * (a + b);
            for (int j = 0; j <= n - 2; j++)
            {
                for (int k = n - 2; k >= j; k--)
                {
                    d[k] -= cnst * d[k + 1];
                }
            }
        }

        public static void ipcshft(double a, double b, double[] d)
        {
            pcshft(-(2.0 + b + a) / (b - a), (2.0 - b - a) / (b - a),  d);
        }

    }
}
 

2 代码格式

using System;namespace Legalsoft.Truffer
{/// <summary>/// Chebyshev approximation/// </summary>public class Chebyshev{private int n { get; set; }private int m { get; set; }private double[] c { get; set; }private double a { get; set; }private double b { get; set; }public Chebyshev(double[] cc, double aa, double bb){this.n = cc.Length;this.m = n;this.c = Globals.CopyFrom(cc);this.a = aa;this.b = bb;}public Chebyshev(double[] d){this.n = d.Length;this.m = n;this.c = new double[n];this.a = -1.0;this.b = 1.0;c[n - 1] = d[n - 1];c[n - 2] = 2.0 * d[n - 2];for (int j = n - 3; j >= 0; j--){c[j] = 2.0 * d[j] + c[j + 2];for (int i = j + 1; i < n - 2; i++){c[i] = (c[i] + c[i + 2]) / 2;}c[n - 2] /= 2;c[n - 1] /= 2;}}/*public Chebyshev(UniVarRealValueFun func, double aa, double bb){new this(func, aa, bb, 50);}*//// <summary>/// Inverse of routine polycofs in Chebyshev: Given an array of polynomial/// coefficients d[0..n - 1], construct an equivalent Chebyshev object./// </summary>/// <param name="func"></param>/// <param name="aa"></param>/// <param name="bb"></param>/// <param name="nn"></param>public Chebyshev(UniVarRealValueFun func, double aa, double bb, int nn = 50){this.n = nn;this.m = nn;this.c = new double[n];this.a = aa;this.b = bb;double[] f = new double[n];double bma = 0.5 * (b - a);double bpa = 0.5 * (b + a);for (int k = 0; k < n; k++){double y = Math.Cos(Math.PI * (k + 0.5) / n);f[k] = func.funk(y * bma + bpa);}double fac = 2.0 / n;for (int j = 0; j < n; j++){double sum = 0.0;for (int k = 0; k < n; k++){sum += f[k] * Math.Cos(Math.PI * j * (k + 0.5) / n);}c[j] = fac * sum;}}public double eval(double x, int m){double d = 0.0;double dd = 0.0;if ((x - a) * (x - b) > 0.0){throw new Exception("x not in range in Chebyshev::eval");}double y = (2.0 * x - a - b) / (b - a);double y2 = 2.0 * (y);for (int j = m - 1; j > 0; j--){double sv = d;d = y2 * d - dd + c[j];dd = sv;}return y * d - dd + 0.5 * c[0];}public double[] getc(){return c;}/// <summary>/// Return a new Chebyshev object that approximates the derivative of the/// existing function over the same range[a, b]./// </summary>/// <returns></returns>public Chebyshev derivative(){double[] cder = new double[n];cder[n - 1] = 0.0;cder[n - 2] = 2 * (n - 1) * c[n - 1];for (int j = n - 2; j > 0; j--){cder[j - 1] = cder[j + 1] + 2 * j * c[j];}double con = 2.0 / (b - a);for (int j = 0; j < n; j++){cder[j] *= con;}return new Chebyshev(cder, a, b);}/// <summary>/// Return a new Chebyshev object that approximates the indefinite integral of/// the existing function over the same range[a, b]. The constant of/// integration is set so that the integral vanishes at a./// </summary>/// <returns></returns>public Chebyshev integral(){double sum = 0.0;double fac = 1.0;double[] cint = new double[n];double con = 0.25 * (b - a);for (int j = 1; j < n - 1; j++){cint[j] = con * (c[j - 1] - c[j + 1]) / j;sum += fac * cint[j];fac = -fac;}cint[n - 1] = con * c[n - 2] / (n - 1);sum += fac * cint[n - 1];cint[0] = 2.0 * sum;return new Chebyshev(cint, a, b);}/// <summary>/// Polynomial coefficients from a Chebyshev fit.Given a coefficient array/// c[0..n-1], this routine returns a coefficient array d[0..n-1] such that/// sum(k= 0, n-1)dky^k = sum(k= 0, n-1)Tk(y)-c0/2. The method is Clenshaw's/// recurrence(5.8.11), but now applied algebraically rather than arithmetically./// </summary>/// <param name="m"></param>/// <returns></returns>public double[] polycofs(int m){double[] d = new double[m];double[] dd = new double[m];for (int j = 0; j < m; j++){d[j] = 0.0;dd[j] = 0.0;}d[0] = c[m - 1];for (int j = m - 2; j > 0; j--){for (int k = m - j; k > 0; k--){double s1v = d[k];d[k] = 2.0 * d[k - 1] - dd[k];dd[k] = s1v;}double s2v = d[0];d[0] = -dd[0] + c[j];dd[0] = s2v;}for (int j = m - 1; j > 0; j--){d[j] = d[j - 1] - dd[j];}d[0] = -dd[0] + 0.5 * c[0];return d;}public int setm(double thresh){while (m > 1 && Math.Abs(c[m - 1]) < thresh){m--;}return m;}public double get(double x){return eval(x, m);}public double[] polycofs(){return polycofs(m);}public static void pcshft(double a, double b, double[] d){int n = d.Length;double cnst = 2.0 / (b - a);double fac = cnst;for (int j = 1; j < n; j++){d[j] *= fac;fac *= cnst;}cnst = 0.5 * (a + b);for (int j = 0; j <= n - 2; j++){for (int k = n - 2; k >= j; k--){d[k] -= cnst * d[k + 1];}}}public static void ipcshft(double a, double b, double[] d){pcshft(-(2.0 + b + a) / (b - a), (2.0 - b - a) / (b - a),  d);}}
}

查看全文

99%的人还看了

猜你感兴趣

版权申明

本文"C#,数值计算——函数计算,切比雪夫近似算法(Chebyshev approximation)的计算方法与源程序":http://eshow365.cn/6-36041-0.html 内容来自互联网,请自行判断内容的正确性。如有侵权请联系我们,立即删除!