zoukankan      html  css  js  c++  java
  • x01.Lab.Numerics: 复幂指数

    复数很有用,因为复数运算即向量运算,而向量在游戏、图像处理等场景必不可少。

    复数很复杂,想一想复数的复数次方,那就不是一般的晕!

    复幂指数离不了欧拉公式:

           e^ix = cosx + i sinx; (自然对数底数 e 的 ix 次方 = cosx + i sinx)

    欧拉公式的详细解释,可参看网上的维基百科。在此基础上,不妨研究一下复数的复数次方:

     public static Complex_R Pow(Complex_R value, Complex_R power)
            {
                if (power == Zero)
                {
                    return One;
                }
                if (value == Zero)
                {
                    return Zero;
                }
    
                double real = value.m_real;
                double imaginary = value.m_imaginary;
                double p_real = power.m_real;
                double p_imaginary = power.m_imaginary;
                double r = Abs(value);
                double rad = Math.Atan2(imaginary, real); 
    
    double v = (p_real * rad) + (p_imaginary * Math.Log(r)); double u = Math.Pow(r, p_real) * Math.Pow(2.7182818284590451, -p_imaginary * rad); return new Complex_R(u * Math.Cos(v), u * Math.Sin(v)); }

     关键的是 u 和 v, 其解释如下:  

        // r = Abs(x+iy); 即复数的模,向量之长度。
        // rad = Math.Atan2(y,x); 即角度,向量之方向。
        // log is Math.Log. 求自然对数。
        // i 是虚数符号,无为算术优先级所干扰。
    
        // 注1. x+iy = r * (cos(rad)+i sin(rad)) = r * e^i rad
        // 见维基百科欧拉公式的 在复分析的应用 一节
    
        (x+iy)^(c+id) 
                => e^( log( (x+iy)^(c+id) ) )  // a = e^log(a)
                => e^( (c+id)*log(x+iy) )      // log(a^b) = b*log(a)    
                => e^((c+id)*log(r* e^i rad))  // 此处用到 注1.
                => e^((c+id)*(log(r) + i rad)) // 乘法而已
                => e^( (c*log(r)-d*rad) + i (c*rad + d*log(r)) )    // v = after i
                => r^c*e^(-d*rad)  * ( cos(v) + i sin(v) )          // u = before *
                => u               * ( cos(v) + i sin(v) )

    顺便,把我用 Net Reflector 反编译的 Complex_R 的代码粘贴如下:

    Complex_R
    namespace x01.Lab.Numerics
    {
        using System;
        using System.Globalization;
        using System.Runtime;
        using System.Runtime.InteropServices;
    
        [AttributeUsage(AttributeTargets.All, Inherited = false)]
        internal sealed class __DynamicallyInvokable : Attribute
        {
        }
    
        [Serializable, StructLayout(LayoutKind.Sequential), __DynamicallyInvokable]
        public struct Complex_R : IEquatable<Complex_R>, IFormattable
        {
            private double m_real;
            private double m_imaginary;
            [__DynamicallyInvokable]
            public static readonly Complex_R Zero;
            [__DynamicallyInvokable]
            public static readonly Complex_R One;
            [__DynamicallyInvokable]
            public static readonly Complex_R ImaginaryOne;
            private const double LOG_10_INV = 0.43429448190325;
            [__DynamicallyInvokable]
            public double Real
            {
                [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
                get
                {
                    return this.m_real;
                }
            }
            [__DynamicallyInvokable]
            public double Imaginary
            {
                [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
                get
                {
                    return this.m_imaginary;
                }
            }
            [__DynamicallyInvokable]
            public double Magnitude
            {
                [__DynamicallyInvokable]
                get
                {
                    return Abs(this);
                }
            }
            [__DynamicallyInvokable]
            public double Phase
            {
                [__DynamicallyInvokable]
                get
                {
                    return Math.Atan2(this.m_imaginary, this.m_real);
                }
            }
            [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
            public Complex_R(double real, double imaginary)
            {
                this.m_real = real;
                this.m_imaginary = imaginary;
            }
    
            [__DynamicallyInvokable]
            public static Complex_R FromPolarCoordinates(double magnitude, double phase)
            {
                return new Complex_R(magnitude * Math.Cos(phase), magnitude * Math.Sin(phase));
            }
    
            [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
            public static Complex_R Negate(Complex_R value)
            {
                return -value;
            }
    
            [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
            public static Complex_R Add(Complex_R left, Complex_R right)
            {
                return (left + right);
            }
    
            [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
            public static Complex_R Subtract(Complex_R left, Complex_R right)
            {
                return (left - right);
            }
    
            [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
            public static Complex_R Multiply(Complex_R left, Complex_R right)
            {
                return (left * right);
            }
    
            [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
            public static Complex_R Divide(Complex_R dividend, Complex_R divisor)
            {
                return (dividend / divisor);
            }
    
            [__DynamicallyInvokable]
            public static Complex_R operator -(Complex_R value)
            {
                return new Complex_R(-value.m_real, -value.m_imaginary);
            }
    
            [__DynamicallyInvokable]
            public static Complex_R operator +(Complex_R left, Complex_R right)
            {
                return new Complex_R(left.m_real + right.m_real, left.m_imaginary + right.m_imaginary);
            }
    
            [__DynamicallyInvokable]
            public static Complex_R operator -(Complex_R left, Complex_R right)
            {
                return new Complex_R(left.m_real - right.m_real, left.m_imaginary - right.m_imaginary);
            }
    
            [__DynamicallyInvokable]
            public static Complex_R operator *(Complex_R left, Complex_R right)
            {
                double real = (left.m_real * right.m_real) - (left.m_imaginary * right.m_imaginary);
                return new Complex_R(real, (left.m_imaginary * right.m_real) + (left.m_real * right.m_imaginary));
            }
    
            [__DynamicallyInvokable]
            public static Complex_R operator /(Complex_R left, Complex_R right)
            {
                double real = left.m_real;
                double imaginary = left.m_imaginary;
                double num3 = right.m_real;
                double num4 = right.m_imaginary;
                if (Math.Abs(num4) < Math.Abs(num3))
                {
                    double num5 = num4 / num3;
                    return new Complex_R((real + (imaginary * num5)) / (num3 + (num4 * num5)), (imaginary - (real * num5)) / (num3 + (num4 * num5)));
                }
                double num6 = num3 / num4;
                return new Complex_R((imaginary + (real * num6)) / (num4 + (num3 * num6)), (-real + (imaginary * num6)) / (num4 + (num3 * num6)));
            }
    
            [__DynamicallyInvokable]
            public static double Abs(Complex_R value)
            {
                if (double.IsInfinity(value.m_real) || double.IsInfinity(value.m_imaginary))
                {
                    return double.PositiveInfinity;
                }
                double num = Math.Abs(value.m_real);
                double num2 = Math.Abs(value.m_imaginary);
                if (num > num2)
                {
                    double num3 = num2 / num;
                    return (num * Math.Sqrt(1.0 + (num3 * num3)));
                }
                if (num2 == 0.0)
                {
                    return num;
                }
                double num4 = num / num2;
                return (num2 * Math.Sqrt(1.0 + (num4 * num4)));
            }
    
            [__DynamicallyInvokable]
            public static Complex_R Conjugate(Complex_R value)
            {
                return new Complex_R(value.m_real, -value.m_imaginary);
            }
    
            [__DynamicallyInvokable]
            public static Complex_R Reciprocal(Complex_R value)
            {
                if ((value.m_real == 0.0) && (value.m_imaginary == 0.0))
                {
                    return Zero;
                }
                return (One / value);
            }
    
            [__DynamicallyInvokable]
            public static bool operator ==(Complex_R left, Complex_R right)
            {
                return ((left.m_real == right.m_real) && (left.m_imaginary == right.m_imaginary));
            }
    
            [__DynamicallyInvokable]
            public static bool operator !=(Complex_R left, Complex_R right)
            {
                if (left.m_real == right.m_real)
                {
                    return !(left.m_imaginary == right.m_imaginary);
                }
                return true;
            }
    
            [__DynamicallyInvokable]
            public override bool Equals(object obj)
            {
                return ((obj is Complex_R) && (this == ((Complex_R)obj)));
            }
    
            [__DynamicallyInvokable]
            public bool Equals(Complex_R value)
            {
                return (this.m_real.Equals(value.m_real) && this.m_imaginary.Equals(value.m_imaginary));
            }
    
            [__DynamicallyInvokable]
            public static implicit operator Complex_R(short value)
            {
                return new Complex_R((double)value, 0.0);
            }
    
            [__DynamicallyInvokable]
            public static implicit operator Complex_R(int value)
            {
                return new Complex_R((double)value, 0.0);
            }
    
            [__DynamicallyInvokable]
            public static implicit operator Complex_R(long value)
            {
                return new Complex_R((double)value, 0.0);
            }
    
            [CLSCompliant(false), __DynamicallyInvokable]
            public static implicit operator Complex_R(ushort value)
            {
                return new Complex_R((double)value, 0.0);
            }
    
            [CLSCompliant(false), __DynamicallyInvokable]
            public static implicit operator Complex_R(uint value)
            {
                return new Complex_R((double)value, 0.0);
            }
    
            [CLSCompliant(false), __DynamicallyInvokable]
            public static implicit operator Complex_R(ulong value)
            {
                return new Complex_R((double)value, 0.0);
            }
    
            [CLSCompliant(false), __DynamicallyInvokable]
            public static implicit operator Complex_R(sbyte value)
            {
                return new Complex_R((double)value, 0.0);
            }
    
            [__DynamicallyInvokable]
            public static implicit operator Complex_R(byte value)
            {
                return new Complex_R((double)value, 0.0);
            }
    
            [__DynamicallyInvokable]
            public static implicit operator Complex_R(float value)
            {
                return new Complex_R((double)value, 0.0);
            }
    
            [__DynamicallyInvokable]
            public static implicit operator Complex_R(double value)
            {
                return new Complex_R(value, 0.0);
            }
    
            //[__DynamicallyInvokable]
            //public static explicit operator Complex(BigInteger value)
            //{
            //    return new Complex((double)value, 0.0);
            //}
    
            [__DynamicallyInvokable]
            public static explicit operator Complex_R(decimal value)
            {
                return new Complex_R((double)value, 0.0);
            }
    
            [__DynamicallyInvokable]
            public override string ToString()
            {
                return string.Format(CultureInfo.CurrentCulture, "({0}, {1})", new object[] { this.m_real, this.m_imaginary });
            }
    
            [__DynamicallyInvokable]
            public string ToString(string format)
            {
                return string.Format(CultureInfo.CurrentCulture, "({0}, {1})", new object[] { this.m_real.ToString(format, CultureInfo.CurrentCulture), this.m_imaginary.ToString(format, CultureInfo.CurrentCulture) });
            }
    
            [__DynamicallyInvokable]
            public string ToString(IFormatProvider provider)
            {
                return string.Format(provider, "({0}, {1})", new object[] { this.m_real, this.m_imaginary });
            }
    
            [__DynamicallyInvokable]
            public string ToString(string format, IFormatProvider provider)
            {
                return string.Format(provider, "({0}, {1})", new object[] { this.m_real.ToString(format, provider), this.m_imaginary.ToString(format, provider) });
            }
    
            [__DynamicallyInvokable]
            public override int GetHashCode()
            {
                int num = 0x5f5e0fd;
                int num2 = this.m_real.GetHashCode() % num;
                int hashCode = this.m_imaginary.GetHashCode();
                return (num2 ^ hashCode);
            }
    
            [__DynamicallyInvokable]
            public static Complex_R Sin(Complex_R value)
            {
                double real = value.m_real;
                double imaginary = value.m_imaginary;
                return new Complex_R(Math.Sin(real) * Math.Cosh(imaginary), Math.Cos(real) * Math.Sinh(imaginary));
            }
    
            [__DynamicallyInvokable]
            public static Complex_R Sinh(Complex_R value)
            {
                double real = value.m_real;
                double imaginary = value.m_imaginary;
                return new Complex_R(Math.Sinh(real) * Math.Cos(imaginary), Math.Cosh(real) * Math.Sin(imaginary));
            }
    
            [__DynamicallyInvokable]
            public static Complex_R Asin(Complex_R value)
            {
                return (-ImaginaryOne * Log((ImaginaryOne * value) + Sqrt(One - (value * value))));
            }
    
            [__DynamicallyInvokable]
            public static Complex_R Cos(Complex_R value)
            {
                double real = value.m_real;
                double imaginary = value.m_imaginary;
                return new Complex_R(Math.Cos(real) * Math.Cosh(imaginary), -(Math.Sin(real) * Math.Sinh(imaginary)));
            }
    
            [__DynamicallyInvokable]
            public static Complex_R Cosh(Complex_R value)
            {
                double real = value.m_real;
                double imaginary = value.m_imaginary;
                return new Complex_R(Math.Cosh(real) * Math.Cos(imaginary), Math.Sinh(real) * Math.Sin(imaginary));
            }
    
            [__DynamicallyInvokable]
            public static Complex_R Acos(Complex_R value)
            {
                return (-ImaginaryOne * Log(value + (ImaginaryOne * Sqrt(One - (value * value)))));
            }
    
            [__DynamicallyInvokable]
            public static Complex_R Tan(Complex_R value)
            {
                return (Sin(value) / Cos(value));
            }
    
            [__DynamicallyInvokable]
            public static Complex_R Tanh(Complex_R value)
            {
                return (Sinh(value) / Cosh(value));
            }
    
            [__DynamicallyInvokable]
            public static Complex_R Atan(Complex_R value)
            {
                Complex_R complex = new Complex_R(2.0, 0.0);
                return ((ImaginaryOne / complex) * (Log(One - (ImaginaryOne * value)) - Log(One + (ImaginaryOne * value))));
            }
    
            [__DynamicallyInvokable]
            public static Complex_R Log(Complex_R value)
            {
                return new Complex_R(Math.Log(Abs(value)), Math.Atan2(value.m_imaginary, value.m_real));
            }
    
            [__DynamicallyInvokable]
            public static Complex_R Log(Complex_R value, double baseValue)
            {
                return (Log(value) / Log(baseValue));
            }
    
            [__DynamicallyInvokable]
            public static Complex_R Log10(Complex_R value)
            {
                return Scale(Log(value), 0.43429448190325);
            }
    
            [__DynamicallyInvokable]
            public static Complex_R Exp(Complex_R value)
            {
                double num = Math.Exp(value.m_real);
                double real = num * Math.Cos(value.m_imaginary);
                return new Complex_R(real, num * Math.Sin(value.m_imaginary));
            }
    
            [__DynamicallyInvokable]
            public static Complex_R Sqrt(Complex_R value)
            {
                return FromPolarCoordinates(Math.Sqrt(value.Magnitude), value.Phase / 2.0);
            }
    
            [__DynamicallyInvokable]
            public static Complex_R Pow(Complex_R value, Complex_R power)
            {
                if (power == Zero)
                {
                    return One;
                }
                if (value == Zero)
                {
                    return Zero;
                }
    
                double real = value.m_real;
                double imaginary = value.m_imaginary;
                double p_real = power.m_real;
                double p_imaginary = power.m_imaginary;
                double r = Abs(value);
                double rad = Math.Atan2(imaginary, real); 
     
                double v = (p_real * rad) + (p_imaginary * Math.Log(r));
                double u = Math.Pow(r, p_real) * Math.Pow(2.7182818284590451, -p_imaginary * rad);
    
                return new Complex_R(u * Math.Cos(v), u * Math.Sin(v));
            }
    
            [__DynamicallyInvokable]
            public static Complex_R Pow(Complex_R value, double power)
            {
                return Pow(value, new Complex_R(power, 0.0));
            }
    
            private static Complex_R Scale(Complex_R value, double factor)
            {
                double real = factor * value.m_real;
                return new Complex_R(real, factor * value.m_imaginary);
            }
    
            static Complex_R()
            {
                Zero = new Complex_R(0.0, 0.0);
                One = new Complex_R(1.0, 0.0);
                ImaginaryOne = new Complex_R(0.0, 1.0);
            }
    
            internal static void Test()
            {
                var c1 = new Complex_R(3.0, 4.0);
                var c2 = new Complex_R(2.0, 0.0);
                Console.WriteLine(Complex_R.Pow(c1, c2));
                Console.WriteLine(c1 * c1 );
    
            }
        }
    }

    有兴趣的不妨在控制台程序中运行一下,我相信会获益良多的。

  • 相关阅读:
    关于Update语句在不同数据库中的差别
    MSIL指令速查表
    一个对于博客园的建议
    代码风格关于if语句
    关于Page.cs文件中注释的一点补充
    在Java、C#和C++中遍历集合
    BPEL4WS的开源Java实现
    【Linux】linux固定ip
    【Linux】【MySQL】MySQL主从数据库
    wpf 写个简单的控件吧
  • 原文地址:https://www.cnblogs.com/china_x01/p/3033199.html
Copyright © 2011-2022 走看看