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

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 代码格式

cs 复制代码
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);
        }

    }
}
相关推荐
秃头佛爷1 分钟前
Python学习大纲总结及注意事项
开发语言·python·学习
待磨的钝刨2 分钟前
【格式化查看JSON文件】coco的json文件内容都在一行如何按照json格式查看
开发语言·javascript·json
浮生如梦_1 小时前
Halcon基于laws纹理特征的SVM分类
图像处理·人工智能·算法·支持向量机·计算机视觉·分类·视觉检测
△曉風殘月〆1 小时前
WPF MVVM入门系列教程(二、依赖属性)
c#·wpf·mvvm
XiaoLeisj2 小时前
【JavaEE初阶 — 多线程】单例模式 & 指令重排序问题
java·开发语言·java-ee
励志成为嵌入式工程师3 小时前
c语言简单编程练习9
c语言·开发语言·算法·vim
逐·風3 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
捕鲸叉3 小时前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer4 小时前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法
Peter_chq4 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端