C#で複素数
どうも必要になりそうなので構造体で複素数型を作ってみる。他に作っている人はたくさんいそうだけど、C#の復習を兼ねてやってみました。以下にソースを貼り付け。
チェックなど一切していない上にけっこう適当です。使用は自己責任で。
/// <summary> /// 複素数 /// </summary> public struct Complex { double real; double imaginary; static string imaginaryUnit = "i"; /// <summary> /// 複素数 /// </summary> /// <param name="re">実部</param> /// <param name="im">虚部</param> public Complex( double re,double im ) { real = re; imaginary = im; } /// <summary> /// 実部 /// </summary> public double Real { get { return real; } set { real = value; } } /// <summary> /// 虚部 /// </summary> public double Imaginary { get { return imaginary; } set { imaginary = value; } } /// <summary> /// 絶対値 /// </summary> public double Abs { get { return Math.Sqrt(Abs2( this )); } set { double a = this.Arg; real = value * Math.Cos( a ); imaginary = value * Math.Sin( a ); } } /// <summary> /// 偏角 [rad] /// </summary> public double Arg { get { return Math.Atan2( imaginary , real ); } set { double v = this.Abs; real = v * Math.Cos( value ); imaginary = v * Math.Sin( value ); } } /// <summary> /// 虚数単位を表す文字(デフォルトは"i") /// </summary> public static string ImaginaryUnit { get { return imaginaryUnit; } set { imaginaryUnit = value; } } #region 算術演算子 #region 加算 public static Complex operator + ( Complex x1,double x2 ) { return new Complex( x1.Real + x2, x1.Imaginary ); } public static Complex operator + ( double x1,Complex x2 ) { return x2 + x1; } public static Complex operator + ( Complex x1,Complex x2 ) { return new Complex( x1.Real + x2.Real, x1.Imaginary + x2.Imaginary ); } #endregion #region 減算 public static Complex operator - ( Complex x1,double x2 ) { return new Complex( x1.Real - x2, x1.Imaginary ); } public static Complex operator - ( double x1,Complex x2 ) { return new Complex( x1 - x2.Real, x2.Imaginary ); } public static Complex operator - ( Complex x1,Complex x2 ) { return new Complex( x1.Real - x2.Real, x1.Real - x2.Real ); } #endregion #region 乗算 public static Complex operator * ( double a, Complex x1 ) { return new Complex( a * x1.Real, a * x1.Imaginary ); } public static Complex operator * ( Complex x1,double a ) { return a * x1; } public static Complex operator * ( Complex x1,Complex x2 ) { return new Complex( x1.Real * x2.Real - x1.Imaginary * x2.Imaginary, x1.Real * x2.Imaginary + x1.Imaginary * x2.Real ); } #endregion #region 除算 public static Complex operator / ( Complex x1,double a ) { return new Complex( x1.Real / a, x1.Imaginary / a ); } public static Complex operator / ( double a, Complex x1 ) { return a * Conj(x1) / Abs2(x1); } public static Complex operator / ( Complex x1,Complex x2 ) { return x1 * Conj(x2) / Abs2(x2); } #endregion #endregion #region 関係演算子 #region 等号 public static bool operator == ( Complex x1,double x2 ) { return x1.Real == x2 && x1.Imaginary == 0; } public static bool operator == ( double x1,Complex x2 ) { return x2 == x1; } public static bool operator == ( Complex x1,Complex x2 ) { return x1.Real == x2.Real && x1.Imaginary == x2.Imaginary; } #endregion #region 不等号 public static bool operator != ( Complex x1,double x2 ) { return x1.Real != x2 || x1.Imaginary != 0; } public static bool operator != ( double x1,Complex x2 ) { return x2 != x1; } public static bool operator != ( Complex x1,Complex x2 ) { return x1.Real != x2.Real || x1.Imaginary != x2.Imaginary; } #endregion public override bool Equals(object obj) { if ( obj is Complex ) { return this == (Complex)obj; } return false; } public override int GetHashCode() { // 注:かなり適当 return real.GetHashCode() + imaginary.GetHashCode(); } #endregion #region 関数 /// <summary> /// 共役複素数 /// </summary> /// <param name="x"></param> /// <returns></returns> public static Complex Conj( Complex x ) { return new Complex( x.Real, -x.Imaginary ); } /// <summary> /// 数値を文字列に変換 /// </summary> /// <returns>文字列</returns> public override string ToString() { if ( imaginary > 0 ) { return real.ToString() + " + " + imaginary.ToString() + ImaginaryUnit; } else if ( imaginary == 0 ) { return real.ToString(); } else { return real.ToString() + " - " + Math.Abs(imaginary).ToString() + ImaginaryUnit; } } /// <summary> /// 数値を極座標形式の文字列に変換 /// </summary> /// <returns></returns> public string ToStringPolar() { return Abs + " * ( cos(" + Arg + ") + sin(" + Arg + "))"; } #endregion #region 内部処理 /// <summary> /// 絶対値の2乗 /// </summary> /// <param name="x"></param> /// <returns></returns> private static double Abs2( Complex x ) { return x.Real * x.Real + x.Imaginary * x.Imaginary; } #endregion }