C#,码海拾贝(02)——复数Complex计算类,《C#数值计算算法编程》源代码升级改进版

一、周长发《C#数值计算算法编程》

1.1图书简介

《C#数值计算算法编程》是2007年1月1日电子工业出版社出版的图书,由周长发编写。

ISBN:9787121032035

本书囊括了近90个实用经典算法,每一个算法都独立成节。每一节都包括算法原理、算法实现和示例3个部分。算法原理部分分别讨论每一种算法的计算原理;算法实现部分讨论用C#实现算法的技巧,针对不同的算法设计了6个算法类,给出完整的类和算法函数的源程序;示例部分介绍算法类的调用方式,给出调用算法的示例源程序、验证算法的示例数据和运算结果。本书内容丰富,讲解细致,实例丰富,适合涉及科学与工程数值计算工作的科研人员工程技术人员、管理人员,以及大专院校相关专业的师生参考阅读。

1.2 目录

第1章 C#与数值计算

1.1 数值计算中存在的问题

1.2 用C#实现数值计算算法的要点

第2章 复数运算

2.1 复数类设计

2.2 复数乘法

2.3 复数除法

2.4 复数的模

2.5 复数的根

2.6 复数的实幂指数

2.7 复数的复幂指数

2.8 复数的自然对数

2.9 复数的正弦

2.10 复数的余弦

2.11 复数的正切

第3章 矩阵运算

3.1 矩阵类设计

3.2 矩阵基础运算

3.3 实矩阵求逆的全选主元高斯—约当法

3.4 复矩阵求逆的全选主元高斯—约当法

3.5 对称正定矩阵的求逆

3.6 托伯利兹矩阵求逆的埃兰特方法

3.7 求行列式值的全选主元高斯消去法

3.8 求矩阵秩的全选主元高斯消去法

3.9 对称正定矩阵的乔里斯基分解与行列式的求值

3.10 矩阵的三角分解

3.11 一般实矩阵的QR分解

3.12 一般实矩阵的奇异值分解

3.13 求广义逆的奇异值分解法

3.14 约化对称矩阵为对称三对角阵的豪斯荷尔德变换法

3.15 实对称三对角阵的全部特征值与特征向量的计算

3.16 约化一般实矩阵为赫申伯格矩阵的初等相似变换法

3.17 求赫申伯格矩阵全部特征值的QR方法

3.18 求实对称矩阵特征值与特征向量的雅可比法

3.19 求实对称矩阵特征值与特征向量的雅可比过关法

第4章 线性代数方程组的求解

4.1 线性方程组类设计

4.2 全选主元高斯消去法

4.3 全选主元高斯一约当消去法

4.4 复系数方程组的全选主元高斯消去法

4.5 复系数方程组的全选主元高斯—约当消去法

4.6 求解三对角线方程组的追赶法

4.7 一般带型方程组的求解

4.8 求解对称方程组的分解法

4.9 求解对称正定方程组的平方根法

4.10 求解大型稀疏方程组的全选主元高斯—约当消去法

4.11 求解对称托伯利兹方程组的列文逊方法

4.12 高斯—赛德尔迭代法

4.13 求解对称正定方程组的共轭梯度法

4.14 求解线性最小二乘问题的豪斯荷尔德变换法

4.]5 求解线性最小二乘问题的广义逆法

4.16 病态方程组的求解

第5章 非线性方程与方程组的求解

5.1 非线性方程与方程组类设计

5.2 求非线性方程实根的对分法

5.3 求非线性方程一个实根的牛顿法

5.4 求非线性方程一个实根的埃特金迭代法

5.5 求非线性方程一个实根的连分式解法

5.6 求实系数代数方程全部根的QR方法

5.7 求实系数代数方程全部根的牛顿下山法

5.8 求复系数代数方程全部根的牛顿下山法

5.9 求非线性方程组一组实根的梯度法

5.10 求非线性方程组一组实根的拟牛顿法

5.11 求非线性方程组最小二乘解的广义逆法

5.12 求非线性方程一个实根的蒙特卡洛法

5.13 求实函数或复函数方程一个复根的蒙特卡洛法

5.14 求非线性方程组一组实根的蒙特卡洛法

第6章 插值

6.1 插值类设计

6.2 一元全区间不等距插值

6.3 一元全区间等距插值

6.4 一元三点不等距插值

6.5 一元三点等距插值

6.6 连分式不等距插值

6.7 连分式等距插值

6.8 埃尔米特不等距插值

6.9 埃尔米特等距插值

6.10 埃特金不等距逐步插值

6.11 埃特金等距逐步插值

6.12 光滑不等距插值

6.13 光滑等距插佔

6.14 第一种边界条件的三次样条函数插值、微商与积分

6.15 第二种边界条件的三次样条函数插值、微商与积分

6.16 第三种边界条件的三次样条函数插值、微商与积分

6.17 二元三点插们

6.18 二元全区间插值

第7章 数值积分

7.1 数值积分类设计

7.2 变步长梯形求枳法

7.3 变步长辛卜生求积法

7.4 自适应梯形求积法

7.5 龙贝格求积法

7.6 计算—维积分的连分式法

7.7 高振荡函数求枳法

7.s 勒让德—高斯求积法

7.9 拉盖尔—高斯求积法

7.10 埃尔米特—高斯求积法

附录A 本书代码的编译和运行

附录B 本书算法类使用指南

B.1 CSharpAlgorithm.Algorithm命名空间概述

B.2 类Complex

B.3 类Matrix

B.4 类LEquations

B.5 类NLEquations

B.6 类Interpolation

B.7 类Integral

二、升级改进版代码

2.1 为什么要改版?

(1)源代码的编写格式比较老了,不适应新的规范。

(2)原始的代码不适应工业化、商业化软件的要求,漏洞不少。

2.2 升级版本的源代码

Complex.cs

using System;

namespace Zhou.CSharp.Algorithm
{
    /// <summary>
    /// 操作复数的类Complex
    /// 作者:周长发
    /// 改编:深度混淆
    /// https://blog.csdn.net/beijinghorn
    /// </summary>
    public class Complex
    {
        /// <summary>
        /// 复数的实部
        /// </summary>
        public double Real { set; get; } = 0.0;
        /// <summary>
        /// 复数的虚部
        /// </summary>
        public double Imaginary { set; get; } = 0.0;
        /// <summary>
        /// 缺省精度
        /// </summary>
        public double Eps { set; get; } = float.Epsilon;

        /// <summary>
        /// 基本构造函数
        /// </summary>
        public Complex()
        {
        }

        /// <summary>
        /// 指定值构造函数
        /// </summary>
        /// <param name="dblX"指定的实部></param>
        /// <param name="dblY"指定的虚部></param>
        public Complex(double dblX, double dblY)
        {
            Real = dblX;
            Imaginary = dblY;
        }

        /// <summary>
        /// 拷贝构造函数
        /// </summary>
        /// <param name="other">源复数</param>
        public Complex(Complex other)
        {
            Real = other.Real;
            Imaginary = other.Imaginary;
        }

        /// <summary>
        /// 根据"a,b"形式的字符串来构造复数,以a为复数的实部,b为复数的虚部
        /// </summary>
        /// <param name="s">"a,b"形式的字符串,a为复数的实部,b为复数的虚部</param>
        /// <param name="sDelim">a, b之间的分隔符</param>
        public Complex(string s, string sDelim = ",")
        {
            SetValue(s, sDelim);
        }

        /// <summary>
        /// 设置复数运算的精度
        /// </summary>
        /// <param name="newEps"新的精度值></param>
        public void SetEps(double newEps)
        {
            Eps = newEps;
        }

        /// <summary>
        /// 取复数的精度值
        /// </summary>
        /// <returns>复数的精度值</returns>
        public double GetEps()
        {
            return Eps;
        }

        /// <summary>
        /// 指定复数的实部
        /// </summary>
        /// <param name="dblX">复数的实部</param>
        public void SetReal(double dblX)
        {
            Real = dblX;
        }

        /// <summary>
        /// 指定复数的虚部
        /// </summary>
        /// <param name="dblY">复数的虚部</param>
        public void SetImag(double dblY)
        {
            Imaginary = dblY;
        }

        /// <summary>
        /// 取复数的实部
        /// </summary>
        /// <returns>复数的实部</returns>
        public double GetReal()
        {
            return Real;
        }

        /// <summary>
        /// 取复数的虚部
        /// </summary>
        /// <returns>复数的虚部</returns>
        public double GetImag()
        {
            return Imaginary;
        }

        /// <summary>
        /// 指定复数的实部和虚部值
        /// </summary>
        /// <param name="real">指定的实部</param>
        /// <param name="imag">指定的虚部</param>
        public void SetValue(double real, double imag)
        {
            SetReal(real);
            SetImag(imag);
        }

        /// <summary>
        /// 将"a,b"形式的字符串转化为复数,以a为复数的实部,b为复数的虚部
        /// </summary>
        /// <param name="s">"a,b"形式的字符串,a为复数的实部,b为复数的虚部</param>
        /// <param name="sDelim">a, b之间的分隔符</param>
        public void SetValue(string s, string sDelim = ",")
        {
#if __OLD__
            int nPos = s.IndexOf(sDelim);
            if (nPos == -1)
            {
                s = s.Trim();
                Real = Double.Parse(s);
                Imaginary = 0.0;
            }
            else
            {
                int nLen = s.Length;
                string sLeft = s.Substring(0, nPos);
                string sRight = s.Substring(nPos + 1, nLen - nPos - 1);
                sLeft = sLeft.Trim();
                sRight = sRight.Trim();
                Real = Double.Parse(sLeft);
                Imaginary = Double.Parse(sRight);
            }
#else
            string[] sa = s.Trim().Split(new char[] { sDelim[0] }, StringSplitOptions.RemoveEmptyEntries);
            if (sa.Length < 2)
            {
                if (Double.TryParse(sa[0], out double r))
                {
                    Real = r;
                    Imaginary = 0.0;
                }
            }
            else
            {
                if (Double.TryParse(sa[0], out double r))
                {
                    Real = r;
                }
                if (Double.TryParse(sa[1], out double s))
                {
                    Imaginary = s;
                }
            }
#endif
        }

        /// <summary>
        /// 重载 + 运算符
        /// </summary>
        /// <param name="cpx1"></param>
        /// <param name="cpx2"></param>
        /// <returns></returns>
        public static Complex operator +(Complex cpx1, Complex cpx2)
        {
            return cpx1.Add(cpx2);
        }

        /// <summary>
        /// 重载 - 运算符
        /// </summary>
        /// <param name="cpx1"></param>
        /// <param name="cpx2"></param>
        /// <returns></returns>
        public static Complex operator -(Complex cpx1, Complex cpx2)
        {
            return cpx1.Subtract(cpx2);
        }

        /// <summary>
        /// 重载 * 运算符
        /// </summary>
        /// <param name="cpx1"></param>
        /// <param name="cpx2"></param>
        /// <returns></returns>
        public static Complex operator *(Complex cpx1, Complex cpx2)
        {
            return cpx1.Multiply(cpx2);
        }

        /// <summary>
        /// 重载 / 运算符
        /// </summary>
        /// <param name="cpx1"></param>
        /// <param name="cpx2"></param>
        /// <returns></returns>
        public static Complex operator /(Complex cpx1, Complex cpx2)
        {
            return cpx1.Divide(cpx2);
        }

        /// <summary>
        /// 重载 double 运算符
        /// </summary>
        /// <param name="cpx"></param>
        public static implicit operator double(Complex cpx)
        {
            return cpx.Abs();
        }

        /// <summary>
        /// 将复数转化为"a+bj"形式的字符串
        /// </summary>
        /// <returns>"a+bj"形式的字符串</returns>
        public override string ToString()
        {
            string s;
            if (Real != 0.0)
            {
                if (Imaginary > 0.0)
                {
                    s = Real.ToString("F") + "+" + Imaginary.ToString("F") + "j";
                }
                else if (Imaginary < 0.0)
                {
                    double absImag = -1 * Imaginary;
                    s = Real.ToString("F") + "-" + absImag.ToString("F") + "j";
                }
                else
                {
                    s = Real.ToString("F");
                }
            }
            else
            {
                if (Imaginary > 0.0)
                {
                    s = Imaginary.ToString("F") + "j";
                }
                else if (Imaginary < 0.0)
                {
                    double absImag = -1 * Imaginary;
                    s = absImag.ToString("F") + "j";
                }
                else
                {
                    s = Real.ToString("F");
                }
            }
            return s;
        }

        /// <summary>
        /// 比较两个复数是否相等
        /// </summary>
        /// <param name="other">用于比较的复数</param>
        /// <returns>相等则为true,否则为false</returns>
        public override bool Equals(object other)
        {
            Complex cpxX = other as Complex;
            if (cpxX == null)
            {
                return false;
            }
            return (Math.Abs(this.Real - cpxX.Real) <= Eps) &&
                (Math.Abs(Imaginary - cpxX.Imaginary) <= Eps);
        }

        /// <summary>
        /// 因为重写了Equals,因此必须重写GetHashCode
        /// </summary>
        /// <returns>返回复数对象散列码</returns>
        public override int GetHashCode()
        {
            return (int)Math.Sqrt(Real * Real + Imaginary * Imaginary);
        }

        /// <summary>
        /// 给复数赋值
        /// </summary>
        /// <param name="cpxX">用于给复数赋值的源复数</param>
        /// <returns></returns>
        public Complex SetValue(Complex cpxX)
        {
            Real = cpxX.Real;
            Imaginary = cpxX.Imaginary;

            return this;
        }

        /// <summary>
        /// 实现复数的加法
        /// </summary>
        /// <param name="cpxX">与指定复数相加的复数</param>
        /// <returns></returns>
        public Complex Add(Complex cpxX)
        {
            double x = Real + cpxX.Real;
            double y = Imaginary + cpxX.Imaginary;

            return new Complex(x, y);
        }

        /// <summary>
        /// 实现复数的减法
        /// </summary>
        /// <param name="cpxX">与指定复数相减的复数</param>
        /// <returns></returns>
        public Complex Subtract(Complex cpxX)
        {
            double x = Real - cpxX.Real;
            double y = Imaginary - cpxX.Imaginary;

            return new Complex(x, y);
        }

        /// <summary>
        /// 实现复数的乘法
        /// </summary>
        /// <param name="cpxX">与指定复数相乘的复数</param>
        /// <returns>指定复数与cpxX相乘之积</returns>
        public Complex Multiply(Complex cpxX)
        {
            double x = Real * cpxX.Real - Imaginary * cpxX.Imaginary;
            double y = Real * cpxX.Imaginary + Imaginary * cpxX.Real;

            return new Complex(x, y);
        }

        /// <summary>
        /// 实现复数的除法
        /// </summary>
        /// <param name="cpxX">与指定复数相除的复数</param>
        /// <returns>指定复数除与cpxX之商</returns>
        public Complex Divide(Complex cpxX)
        {
            double x, y;
            if (cpxX.Abs() < float.Epsilon)
            {
                return new Complex(float.MaxValue, float.MaxValue);
            }
            if (Math.Abs(cpxX.Real) >= Math.Abs(cpxX.Imaginary))
            {
                double e = cpxX.Imaginary / cpxX.Real;
                double f = cpxX.Real + e * cpxX.Imaginary;

                double x = (Real + Imaginary * e) / f;
                double y = (Imaginary - Real * e) / f;
                return new Complex(x, y);
            }
            else
            {
                double e = cpxX.Real / cpxX.Imaginary;
                double f = cpxX.Imaginary + e * cpxX.Real;

                double x = (Real * e + Imaginary) / f;
                double y = (Imaginary * e - Real) / f;
                return new Complex(x, y);
            }
        }

        /// <summary>
        /// 计算复数的模
        /// </summary>
        /// <returns>指定复数的模</returns>
        public double Abs()
        {
            // 求取实部和虚部的绝对值
            double x = Math.Abs(Real);
            double y = Math.Abs(Imaginary);

            if (x < float.Epsilon)
            {
                return y;
            }
            if (y < float.Epsilon)
            {
                return x;
            }
            // 计算模
            if (x > y)
            {
                double yx = y / x;
                return (x * Math.Sqrt(1.0 + (yx) * (yx)));
            }
            else
            {
                double xy = x / y;
                return (y * Math.Sqrt(1.0 + (xy) * (xy)));
            }
        }

        /// <summary>
        /// 计算复数的根
        /// </summary>
        /// <param name="n">待求根的根次</param>
        /// <param name="cpxR">Complex型数组,长度为n,返回复数的所有根</param>
        public void Root(int n, out Complex[] cpxR)
        {
            cpxR = new Complex[n];
            if (n < 1)
            {
                return;
            }
            double q = Math.Atan2(Imaginary, Real);
            double r = Math.Sqrt(Real * Real + Imaginary * Imaginary);
            if (r != 0)
            {
                r = (1.0 / n) * Math.Log(r);
                r = Math.Exp(r);
            }

            for (int k = 0; k <= n - 1; k++)
            {
                double t = (2.0 * k * Math.PI + q) / n;
                cpxR[k] = new Complex(r * Math.Cos(t), r * Math.Sin(t));
            }
        }

        /// <summary>
        /// 计算复数的实幂指数
        /// </summary>
        /// <param name="dblW">待求实幂指数的幂次</param>
        /// <returns>复数的实幂指数值</returns>
        public Complex Pow(double dblW)
        {
            // 特殊值处理
            if (Math.Abs(Real) < float.Epsilon && Math.Abs(Imaginary) < float.Epsilon)
            {
                return new Complex(0.0, 0.0);
            }

            // 幂运算公式中的三角函数运算
            double t;
            if (Math.Abs(Real) < float.Epsilon)
            {
                t = (Imaginary > 0.0) ? Math.PI * 0.5 : (-Math.PI * 0.5);
            }
            else
            {
                if (Real > 0.0)
                {
                    t = Math.Atan2(Imaginary, Real);
                }
                else
                {
                    if (Imaginary >= 0.0)
                    {
                        t = Math.Atan2(Imaginary, Real) + Math.PI;
                    }
                    else
                    {
                        t = Math.Atan2(Imaginary, Real) - Math.PI;
                    }
                }
            }

            // 模的幂
            double r = Math.Exp(dblW * Math.Log(Math.Sqrt(Real * Real + Imaginary * Imaginary)));

            // 复数的实幂指数
            return new Complex(r * Math.Cos(dblW * t), r * Math.Sin(dblW * t));
        }

        /// <summary>
        /// 计算复数的复幂指数
        /// </summary>
        /// <param name="cpxW">待求复幂指数的幂次</param>
        /// <param name="n">控制参数,默认值为0。当n=0时,求得的结果为复幂指数的主值</param>
        /// <returns>复数的复幂指数值</returns>
        public Complex Pow(Complex cpxW, int n)
        {
            double s;
            // 特殊值处理
            if (Math.Abs(Real) < float.Epsilon)
            {
                if (Math.Abs(Imaginary) < float.Epsilon)
                {
                    return new Complex(0.0, 0.0);
                }
                s = (Math.PI * 0.5) * (Math.Abs(Imaginary) / Imaginary + 4.0 * n);
            }
            else
            {
                s = 2.0 * Math.PI * n + Math.Atan2(Imaginary, Real);
                if (Real < 0.0)
                {
                    if (Imaginary > 0.0)
                    {
                        s = s + Math.PI;
                    }
                    else
                    {
                        s = s - Math.PI;
                    }
                }
            }

            // 求幂运算公式
            double r = 0.5 * Math.Log(Real * Real + Imaginary * Imaginary);
            double v = cpxW.Real * r + cpxW.Imaginary * s;
            double u = Math.Exp(cpxW.Real * r - cpxW.Imaginary * s);

            return new Complex(u * Math.Cos(v), u * Math.Sin(v));
        }

        /// <summary>
        /// 计算复数的自然对数
        /// </summary>
        /// <returns></returns>
        public Complex Log()
        {
            double p = Math.Log(Math.Sqrt(Real * Real + Imaginary * Imaginary));
            return new Complex(p, Math.Atan2(Imaginary, Real));
        }

        /// <summary>
        /// 计算复数的正弦
        /// </summary>
        /// <returns></returns>
        public Complex Sin()
        {
            // 切比雪夫公式的常数系数
            double[] c = new double[6] {
                1.13031820798497,
                0.04433684984866,
                0.00054292631191,
                0.00000319843646,
                0.00000001103607,
                0.00000000002498
            };

            double y1 = Math.Exp(Imaginary);
            double x = 0.5 * (y1 + 1.0 / y1);
            double br = 0.0;
            double y;
            if (Math.Abs(Imaginary) >= 1.0)
            {
                y = 0.5 * (y1 - 1.0 / y1);
            }
            else
            {
                double b1 = 0;
                double b2 = 0;
                y1 = 2.0 * (2.0 * Imaginary * Imaginary - 1.0);
                for (int i = 5; i >= 0; --i)
                {
                    br = y1 * b1 - b2 - c[i];
                    if (i != 0)
                    {
                        b2 = b1;
                        b1 = br;
                    }
                }

                y = Imaginary * (br - b1);
            }

            // 组合计算结果
            x = x * Math.Sin(Real);
            y = y * Math.Cos(Real);

            return new Complex(x, y);
        }

        /// <summary>
        /// 计算复数的余弦
        /// </summary>
        /// <returns></returns>
        public Complex Cos()
        {
            // 切比雪夫公式的常数系数
            double[] c = new double[6] {
                1.13031820798497,
                0.04433684984866,
                0.00054292631191,
                0.00000319843646,
                0.00000001103607,
                0.00000000002498
            };

            double y1 = Math.Exp(Imaginary);
            double x = 0.5 * (y1 + 1.0 / y1);
            double br = 0.0;
            double y;
            if (Math.Abs(Imaginary) >= 1.0)
            {
                y = 0.5 * (y1 - 1.0 / y1);
            }
            else
            {
                double b1 = 0;
                double b2 = 0;
                y1 = 2.0 * (2.0 * Imaginary * Imaginary - 1.0);
                for (int i = 5; i >= 0; --i)
                {
                    br = y1 * b1 - b2 - c[i];
                    if (i != 0)
                    {
                        b2 = b1;
                        b1 = br;
                    }
                }

                y = Imaginary * (br - b1);
            }

            // 组合计算结果
            x = x * Math.Cos(Real);
            y = -y * Math.Sin(Real);

            return new Complex(x, y);
        }

        /// <summary>
        /// 计算复数的正切
        /// </summary>
        /// <returns></returns>
        public Complex Tan()
        {
            return Sin().Divide(Cos());
        }
    }
}

后面陆续发布其他 类Class 的升级版本。

  1. 复数类 Complex.cs

  1. 积分类 Integral.cs

  1. 插值类 Interpolation.cs

  1. 线性方程求解 LEquations.cs

  1. 矩阵类 Matrix.cs

  1. 非线性方程求解 NLEquations.cs

猜你喜欢

转载自blog.csdn.net/beijinghorn/article/details/129777619