复数运算类

来源:互联网 发布:乐视有线网络设置方法 编辑:程序博客网 时间:2024/05/16 01:32

  public class Complex
    {
        public double Real { set; get; }
        public double Imaginary { set; get; }

        private double m_Eps = 0.001;

        /// <summary>
        /// 精度
        /// </summary>
        public double Eps { set { m_Eps = value; } get { return m_Eps; } }

        public Complex()
        { }

        public Complex(double x, double y)
        {
            this.Real = x;
            this.Imaginary = y;
        }

        public Complex(Complex cpx)
        {
            this.Real = cpx.Real;
            this.Imaginary = cpx.Imaginary;
        }
        //public Complex(string s, string sDelim)
        //{
        //    int nPos = s.IndexOf(sDelim);
        //    if (nPos == -1)
        //    {
        //        s = s.Trim();
        //        Real = Double.Parse(s);
        //        Imaginary = 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);
        //    }
        //}

        public static Complex operator +(Complex cpx1, Complex cpx2)
        {
            return cpx1.Add(cpx2);
        }
        public static Complex operator -(Complex cpx1, Complex cpx2)
        {
            return cpx1.Subtract(cpx2);
        }

        public static Complex operator *(Complex cpx1, Complex cpx2)
        {
            return cpx1.Multiply(cpx2);
        }
        public static Complex operator /(Complex cpx1, Complex cpx2)
        {
            return cpx1.Divide(cpx2);
        }

        public static implicit operator double(Complex cpx)
        {
            return cpx.Abs();
        }

        public override string ToString()
        {
            string s;
            if (Real != 0.0)
            {
                if (Imaginary > 0)
                    s = Real.ToString("F") + "+" + Imaginary.ToString("F") + "i";
                else if (Imaginary < 0)
                {
                    double absImag = -1 * Imaginary;
                    s = Real.ToString("F") + "-" + absImag.ToString("F");
                }
                else
                {
                    s = Real.ToString("F");
                }
            }
            else
            {
                if (Imaginary > 0)
                    s = Imaginary.ToString("F") + "i";
                else if (Imaginary < 0)
                {
                    double absImag = -1 * Imaginary;
                    s = absImag.ToString("F") + "i";
                }
                else
                    s = Real.ToString("F");
            }
            return s;
        }
        public override bool Equals(object obj)
        {
            Complex cmpx = obj as Complex;
            if (cmpx == null)
                return false;
            return Math.Abs(this.Real - cmpx.Real) <= m_Eps
                    && Math.Abs(this.Imaginary - cmpx.Imaginary) <= m_Eps;
        }


        public override int GetHashCode()
        {
            return (int)Math.Sqrt(Real * Real + Imaginary * Imaginary);
        }

        /// <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);
        }

        //复数的乘法(a,b)*(x,y) == (ax-by,ay+bx)
        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);
        }

        //复数的除法(a,b)/(x,y)
        //|c|>=|d| [(a+b*(d/c))+j(b-a*(d/c))]/(c+d*(d/c))
        //|c|<|d| [(a*(c/d)+b)+j(b*(c/d-a)]/(c(c/d)+d);
        public Complex Divide(Complex cpxX)
        {
            double e, f, x, y;
            if (Math.Abs(cpxX.Real) >= Math.Abs(cpxX.Imaginary))
            {
                e = cpxX.Imaginary / cpxX.Real;
                f = cpxX.Real + cpxX.Imaginary * e;

                x = (Real + Imaginary * e) / f;
                y = (Imaginary - Real * e) / f;
            }
            else
            {
                e = cpxX.Real / cpxX.Imaginary;
                f = cpxX.Real * e + cpxX.Imaginary;

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

        //复数的求模运算
        //
        public double Abs()
        {
            double x = Math.Abs(Real);
            double y = Math.Abs(Imaginary);

            if (Real == 0)
                return y;
            if (Imaginary == 0)
                return x;

            if (x > y)
                return (x * Math.Sqrt(1 + (y / x) * (y / x)));
            return (y * Math.Sqrt(1 + (x / y) * (x / y)));
        }

        //计算复数的根
        public void Root(int n, Complex[] cpxR)
        {
            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 * 3.1415926 + q) / n;
                cpxR[k] = new Complex(r * Math.Cos(t), r * Math.Sin(t));
            }

        }

        //复数的实幂运算
        //z^w=r^w(cos WQ+j sinQ)  W=指数 Q为Z=x+jy的幅角 r为复数的模
        public Complex Pow(double dblw)
        {
            // 常量
            const double PI = 3.14159265358979;

            //局部变量
            double r, t;

            //特殊值处理
            if ((Real == 0) && (Imaginary == 0))
                return new Complex(0, 0);

            //幂运算公式中的三角函数运算
            if (Real == 0)
            {
                if (Imaginary > 0)
                    t = 1.5707963268;
                else
                    t = -1.5707963268;
            }
            else
            {
                if (Real > 0)
                    t = Math.Atan2(Imaginary, Real) + PI;
                else
                    t = Math.Atan2(Imaginary, Real) - PI;
            }

            //模的幂
            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));
        }

        //计算复数的复幂指数
        public Complex Pow(Complex cpxX, int n)
        {
            //常量
            const double PI = 3.14159265358979;

            //局部变量
            double r, s, u, v;

            //特殊值处理
            if (Real == 0)
            {
                if (Imaginary == 0)
                    return new Complex(0, 0);
                s = 1.5707963268 * (Math.Abs(Imaginary) / Imaginary + 4 * n);
            }
            else
            {
                s = 2 * PI * n + Math.Atan2(Imaginary, Real);
                if (Real < 0)
                {
                    if (Imaginary > 0)
                        s = s + PI;
                    else
                        s = s - PI;
                }
            }

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

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

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

        public Complex Sin()
        {
            int i;
            double x, y, y1, br, b1, b2;
            double[] c = new double[6];

            //切比雪夫公式的常数系数
            c[0] = 1.13031820798497;
            c[1] = 0.04433684984866;
            c[2] = 0.00054292631191;
            c[3] = 0.00000319843646;
            c[4] = 0.00000001103607;
            c[5] = 0.00000000002498;

            y1 = Math.Exp(Imaginary);
            x = 0.5 * (y1 + 1 / y1);
            br = 0;
            if (Math.Abs(Imaginary) >= 1)
                y = 0.5 * (y1 - 1 / y1);
            else
            {
                b1 = 0;
                b2 = 0;
                y1 = 2 * (2 * Imaginary * Imaginary - 1);
                for (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 = x * Math.Cos(Real);
            return new Complex(x, y);
        }

        //计算复数的余弦
        public Complex Cos()
        {
            int i;
            double x, y, y1, br, b1, b2;
            double[] c = new double[6];

            //切比雪夫公式的常数系统
            c[0] = 1.13001820798497;
            c[1] = 0.04433684984866;
            c[2] = 0.00054292631191;
            c[3] = 0.00000319843646;
            c[4] = 0.00000001103607;
            c[5] = 0.00000000002498;

            y1 = Math.Exp(Imaginary);
            x = 0.5 * (y1 + 1 / y1);
            br = 0;
            if (Math.Abs(Imaginary) >= 1)
                y = 0.5 * (y1 - 1 / y1);
            else
            {
                b1 = 0;
                b2 = 0;
                y1 = 2 * (2 * Imaginary * Imaginary - 1);
                for (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);
        }

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