C#数学运算类

对数学关心的朋友,可以看看这篇文章。

我们知道对诸如方程求根或数值积分的问题,即使算法编出来,每次也需要编一个待求根或数值积分的函数,这样做真是繁琐,效率非常低。我这里用C#.net(beta2)编了一个一元实函数类,使问题简化了不少。比如f(x)=cos(x)^3这样一个函数,用我的方法可表示为Function f=Function.Cos^3就可以了。为求f(1),可按下面方式f.Fun(1)即可。是不是还可以呀。

我们知道初等函数可由六类基本初等函数经过有限次的加减乘除和复合步骤得到的能用一个式子表达的函数。在这个类中就提供了这六类基本初等函数,加用+表示,减用-表示,乘用*表示,除用/表示,乘方用^表示,复合用&表示,都是运算符重载。

习惯表达Function类表达
f(x)=sin(x)+cos(x)Function f=Function.Sin+Function.Cos
f(x)=exp(x)-Ln(x)Function f=Function.Exp-Function.Log
f(x)=sin(x)*Ln(x)Funciton f=Function.Sin*Function.Ln
f(x)=sin(x)/cos(x)Function f=Function.Sin/Function.Cos
乘方f(x)=exp(x)^3Function f=Function.Exp^3
复合f(x)=exp(sin(x))Function f=Function.Exp&Function.Sin

注:

  1. 由于C#对大小写敏感,请大家注意字母的大小写
  2. 源代码中有关于类的注释,相信大家可以读懂
//===========================================
//源代码
//===========================================
namespace Maths
{
    using System;
    public delegate double Func(double a);
    //一元实函数类
    public class Function
    {
        private FuncNode[] fnode;  //节点数组
                                   //构造函数1,生成c常函数
        public Function(double c)
        {
            this.fnode = new FuncNode[1];
            this.fnode[0] = new Func(Function.unit);
            fnode[0].Yfactor = c;
        }
        //构造函数2
        public Function(FuncNode node)
        {
            this.fnode = new FuncNode[1];
            fnode[0] = node;
        }
        //构造函数3
        public Function(FuncNode[] fnode)
        {
            this.fnode = new FuncNode[fnode.Length];
            for (int i = 0; i < fnode.Length; i++)
                this.fnode[i] = fnode[i];
        }
        //两个函数的和
        public static Function operator +(Function f1, Function f2)
        {
            FuncNode[] fnode = new FuncNode[f1.fnode.Length + f2.fnode.Length + 1];
            fnode[0] = Operator.cadd;
            for (int i = 1; i <= f1.fnode.Length; i++)
                fnode[i] = f1.fnode[i - 1];
            for (int i = f1.fnode.Length + 1; i < fnode.Length; i++)
                fnode[i] = f2.fnode[i - f1.fnode.Length - 1];
            return new Function(fnode);
        }
        //两个函数的差
        public static Function operator -(Function f1, Function f2)
        {
            FuncNode[] fnode = new FuncNode[f1.fnode.Length + f2.fnode.Length + 1];
            fnode[0] = Operator.csub;
            for (int i = 1; i <= f1.fnode.Length; i++)
                fnode[i] = f1.fnode[i - 1];
            for (int i = f1.fnode.Length + 1; i < fnode.Length; i++)
                fnode[i] = f2.fnode[i - f1.fnode.Length - 1];
            return new Function(fnode);
        }
        //两个函数的积
        public static Function operator *(Function f1, Function f2)
        {
            FuncNode[] fnode = new FuncNode[f1.fnode.Length + f2.fnode.Length + 1];
            fnode[0] = Operator.cmul;
            for (int i = 1; i <= f1.fnode.Length; i++)
                fnode[i] = f1.fnode[i - 1];
            for (int i = f1.fnode.Length + 1; i < fnode.Length; i++)
                fnode[i] = f2.fnode[i - f1.fnode.Length - 1];
            return new Function(fnode);
        }
        //两个函数的商
        public static Function operator /(Function f1, Function f2)
        {
            FuncNode[] fnode = new FuncNode[f1.fnode.Length + f2.fnode.Length + 1];
            fnode[0] = Operator.cdiv;
            for (int i = 1; i <= f1.fnode.Length; i++)
                fnode[i] = f1.fnode[i - 1];
            for (int i = f1.fnode.Length + 1; i < fnode.Length; i++)
                fnode[i] = f2.fnode[i - f1.fnode.Length - 1];
            return new Function(fnode);
        }
        //两个函数的乘方
        public static Function operator ^(Function f1, Function f2)
        {
            FuncNode[] fnode = new FuncNode[f1.fnode.Length + f2.fnode.Length + 1];
            fnode[0] = Operator.cpow;
            for (int i = 1; i <= f1.fnode.Length; i++)
                fnode[i] = f1.fnode[i - 1];
            for (int i = f1.fnode.Length + 1; i < fnode.Length; i++)
                fnode[i] = f2.fnode[i - f1.fnode.Length - 1];
            return new Function(fnode);
        }
        //两个函数的符合f&g(x)=f(g(x))
        public static Function operator &(Function f1, Function f2)
        {
            FuncNode[] fnode = new FuncNode[f1.fnode.Length + f2.fnode.Length + 1];
            fnode[0] = Operator.ccom;
            for (int i = 1; i <= f1.fnode.Length; i++)
                fnode[i] = f1.fnode[i - 1];
            for (int i = f1.fnode.Length + 1; i < fnode.Length; i++)
                fnode[i] = f2.fnode[i - f1.fnode.Length - 1];
            return new Function(fnode);
        }
        //计算复杂函数的值
        public double Fun(double x)
        {
            return this.FunV(x, 0, fnode.Length - 1);
        }
        public double FunV(double x, int low, int high)
        {
            if (low == high)
                return fnode[low].Fun(x);
            else
            {
                int signnum = 0;
                int funcnum = 0;
                int mid = 0;
                for (int i = low; i <= high; i++)
                {
                    if (fnode[i].IsFunction) funcnum++;
                    else
                        signnum++;
                    if (funcnum == signnum)
                    {
                        mid = i;
                        break;
                    }
                }
                double v = 0;
                switch (fnode[low].Oper)
                {
                    case Operator.cadd: v = this.FunV(x, low + 1, mid) + this.FunV(x, mid + 1, high); break;
                    case Operator.csub: v = this.FunV(x, low + 1, mid) - this.FunV(x, mid + 1, high); break;
                    case Operator.cmul: v = this.FunV(x, low + 1, mid) * this.FunV(x, mid + 1, high); break;
                    case Operator.cdiv: v = this.FunV(x, low + 1, mid) / this.FunV(x, mid + 1, high); break;
                    case Operator.cpow: v = Math.Pow(this.FunV(x, low + 1, mid), this.FunV(x, mid + 1, high)); break;
                    case Operator.ccom: v = this.FunV(this.FunV(x, mid + 1, high), low + 1, mid); break;
                }
                return v;
            }
        }
        //                                --
        //下面是六类基本初等函数的Function类化
        //                                --
        //单位函数
        public static Function Unit
        {
            get
            {
                FuncNode node = new Func(Function.unit);
                return new Function(node);
            }
        }
        //常函数c
        public static Function ConstFunc(double c)
        {
            FuncNode node = new Func(Function.unit);
            node.Yfactor = c;
            return new Function(node);
        }
        //幂函数x^a
        public static Function Pow(double a)
        {
            FuncNode node = new Func(Function.FuncX);
            Function f1 = new Function(node);
            return f1 ^ Function.ConstFunc(a);
        }
        //指数函数
        public static Function Exp
        {
            get
            {
                FuncNode node = new Func(Math.Exp);
                return new Function(node);
            }
        }
        //对数函数
        public static Function Log
        {
            get
            {
                FuncNode node = new Func(Math.Log);
                return new Function(node);
            }
        }
        //正弦函数
        public static Function Sin
        {
            get
            {
                FuncNode node = new Func(Math.Sin);
                return new Function(node);
            }
        }
        //余弦函数
        public static Function Cos
        {
            get
            {
                FuncNode node = new Func(Math.Cos);
                return new Function(node);
            }
        }
        //正切函数
        public static Function Tan
        {
            get
            {
                FuncNode node = new Func(Math.Tan);
                return new Function(node);
            }
        }
        //余切函数
        public static Function Cot
        {
            get
            {
                FuncNode node = new Func(Function.CTan);
                return new Function(node);
            }
        }
        //余切函数的补充
        private static double CTan(double x)
        {
            return 1.0 / Math.Tan(x);
        }
        //反正弦函数
        public static Function Asin
        {
            get
            {
                FuncNode node = new Func(Math.Asin);
                return new Function(node);
            }
        }
        //反余弦函数
        public static Function Acos
        {
            get
            {
                FuncNode node = new Func(Math.Acos);
                return new Function(node);
            }
        }
        //反正切函数
        public static Function Atan
        {
            get
            {
                FuncNode node = new Func(Math.Atan);
                return new Function(node);
            }
        }
        //反余切函数
        public static Function Acot
        {
            get
            {
                FuncNode node = new Func(Function.ACtan);
                return new Function(node);
            }
        }
        //反余切函数的补充函数
        private static double ACtan(double x)
        {
            return Math.PI / 2 - Math.Atan(x);
        }
        //
        //单位函数1
        private static double unit(double x)
        {
            return 1;
        }
        private static double FuncX(double x)
        {
            return x;
        }
        //重载
        public override string ToString()
        {
            return this.toString(0, fnode.Length - 1);
        }
        //double到本类的隐式转换
        public static implicit operator Function(double a)
        {
            return Function.ConstFunc(a);
        }
        //函数表达式获取函数
        private string toString(int low, int high)
        {
            if (low == high)
                return "(" + fnode[low].ToString() + ")";
            else
            {
                int signnum = 0;
                int funcnum = 0;
                int mid = 0;
                for (int i = low; i <= high; i++)
                {
                    if (fnode[i].IsFunction) funcnum++;
                    else
                        signnum++;
                    if (funcnum == signnum)
                    {
                        mid = i;
                        break;
                    }
                }
                string str = "";
                switch (fnode[low].Oper)
                {
                    case Operator.cadd: str = "(" + this.toString(low + 1, mid) + "+" + this.toString(mid + 1, high) + ")"; break;
                    case Operator.csub: str = "(" + this.toString(low + 1, mid) + "-" + this.toString(mid + 1, high) + ")"; break;
                    case Operator.cmul: str = "(" + this.toString(low + 1, mid) + "*" + this.toString(mid + 1, high) + ")"; break;
                    case Operator.cdiv: str = "(" + this.toString(low + 1, mid) + "/" + this.toString(mid + 1, high) + ")"; break;
                    case Operator.cpow: str = "(" + this.toString(low + 1, mid) + "^" + this.toString(mid + 1, high) + ")"; break;
                    case Operator.ccom: str = "(" + this.toString(low + 1, mid) + "&" + this.toString(mid + 1, high) + ")"; break;
                }
                return str;
            }
        }
    }
    //                                            ---
    //函数节点类
    //                                            ---
    public class FuncNode
    {
        private Operator oper;
        private Func f;
        private double yfactor; //y的伸缩因子
        private double xfactor; //x的伸缩因子
        private double addconst; //Yfactor*y后的平移量
        private double xshift;  //Xfactor*x后的平移量
                                //构造函数1
        public FuncNode(Operator oper)
        {
            if (oper == Operator.empty)
                throw new ExceptionFuncNode("结构体的构造函数FuncNode(Operator )的输入参数不能为Operator.empty");
            this.oper = oper;
            this.f = null;
            this.yfactor = 1;
            this.xfactor = 1;
            this.addconst = 0;
            this.xshift = 0;
        }
        //构造函数2
        public FuncNode(Func f)
        {
            if (f == null)
                throw new ExceptionFuncNode("结构体的构造函数FuncNode(Func )的输入参数不能为null");
            this.oper = Operator.empty;
            this.f = f;
            this.yfactor = 1;
            this.xfactor = 1;
            this.addconst = 0;
            this.xshift = 0;
        }
        //委派Func到本类的隐式转换
        public static implicit operator FuncNode(Func f)
        {
            FuncNode fnode = new FuncNode(f);
            return fnode;
        }
        public static implicit operator FuncNode(Operator oper)
        {
            return new FuncNode(oper);
        }
        //属性
        public bool IsFunction
        {
            get
            {
                if (this.oper != Operator.empty) return false;
                else
                    return true;
            }
        }
        //若节点表示的是函数,则可以求值
        public double Fun(double x)
        {
            if (!this.IsFunction) throw new ExceptionFuncNode("本节点不是函数,不可以求函数值");
            return yfactor * f(xfactor * x + xshift) + addconst;
        }
        //属性
        public Operator Oper
        {
            get
            {
                if (this.oper == Operator.empty) throw new ExceptionFuncNode("本节点是函数");
                return this.oper;
            }
            set
            {
                if (this.f != null) this.oper = value;
                else
                    throw new ExceptionFuncNode("本节点是函数");
            }
        }
        //属性
        public Func F
        {
            get
            {
                if (this.oper != Operator.empty) throw new ExceptionFuncNode("本节点是运算符");
                return this.f;
            }
            set
            {
                if (this.oper != Operator.empty) throw new ExceptionFuncNode("本节点是运算符");
                this.f = value;
            }
        }
        //属性
        public double Yfactor
        {
            get
            {
                if (this.oper != Operator.empty) throw new ExceptionFuncNode("本节点是运算符");
                return this.yfactor;
            }
            set
            {
                if (this.oper != Operator.empty) throw new ExceptionFuncNode("本节点是运算符");
                this.yfactor = value;
            }
        }
        //属性
        public double Xfactor
        {
            get
            {
                if (this.oper != Operator.empty) throw new ExceptionFuncNode("本节点是运算符");
                return this.xfactor;
            }
            set
            {
                if (this.oper != Operator.empty) throw new ExceptionFuncNode("本节点是运算符");
                if (value == 0) throw new ExceptionFuncNode("x的伸缩量不能为0");
                this.xfactor = value;
            }
        }
        //属性
        public double Addconst
        {
            get
            {
                if (this.oper != Operator.empty) throw new ExceptionFuncNode("本节点是运算符");
                return this.addconst;
            }
            set
            {
                if (this.oper != Operator.empty) throw new ExceptionFuncNode("本节点是运算符");
                this.addconst = value;
            }
        }
        //属性
        public double Xshift
        {
            get
            {
                if (this.oper != Operator.empty) throw new ExceptionFuncNode("本节点是运算符");
                return this.xshift;
            }
            set
            {
                if (this.oper != Operator.empty) throw new ExceptionFuncNode("本节点是运算符");
                this.xshift = value;
            }
        }
        //重载
        public override string ToString()
        {
            if (this.oper != Operator.empty)
            {
                string str = "";
                switch (this.oper)
                {
                    case Operator.cadd: str = "+"; break;
                    case Operator.csub: str = "-"; break;
                    case Operator.cmul: str = "*"; break;
                    case Operator.cdiv: str = "/"; break;
                    case Operator.cpow: str = "^"; break;
                    case Operator.ccom: str = "&"; break;
                }
                return str;
            }
            else
            {
                string str;
                str = this.f.Method.ToString().Remove(0, 7);
                str = str.Remove(str.Length - 7, 6);
                if (this.yfactor == 0)
                {
                    if (this.addconst < 0) return "(" + this.addconst + ")";
                    return this.addconst.ToString();
                }
                else
                {
                    if (this.yfactor != 1) str = this.yfactor + "*" + str;
                    if (this.xfactor != 1) str = str.Insert(str.Length - 1, this.xfactor + "*x");
                    else
                        str = str.Insert(str.Length - 1, "x");
                    if (this.xshift > 0)
                        str = str.Insert(str.Length - 1, "+" + this.xshift);
                    else if (this.xshift < 0)
                        str = str.Insert(str.Length - 1, this.xshift.ToString());
                    if (this.addconst > 0)
                        str = str + "+" + this.addconst;
                    else if (this.addconst < 0)
                        str = str + this.addconst.ToString();
                }
                return str;
            }
        }
    }
    public class ExceptionFuncNode : System.Exception
    {
        private string errorMessage;
        public string ErrorMessage
        {
            get
            {
                return this.errorMessage;
            }
        }
        //构造函数
        public ExceptionFuncNode(string errormessage)
        {
            this.errorMessage = errormessage;
        }
        public override string ToString()
        {
            return this.ErrorMessage;
        }
    }
    public enum Operator
    {
        cadd,
        csub,
        cmul,
        cdiv,
        cpow,
        ccom,
        empty
    }
}
Contributors: FHL