次の方法で共有


System.Numerics.Complex 構造体

この記事では、この API のリファレンス ドキュメントへの補足的な解説を提供します。

複素数は、実数部と虚数部で構成される数値です。 複素数 z は通常、 z = x + yi形式で記述されます。ここで、 xy は実数で、 i はプロパティ i2 = -1 を持つ虚数単位です。 複素数の実数は xで表され、複素数の虚数部分は yで表されます。

Complex型は、複素数をインスタンス化および操作するときにデカルト座標系 (実数、虚数) を使用します。 複素数は、複合平面と呼ばれる 2 次元座標系の点として表すことができます。 複素数の実数部分は x 軸 (横軸) に配置され、虚数部は y 軸 (縦軸) に配置されます。

複素平面内の任意の点は、極座標系を使用して、その絶対値に基づいて表現することもできます。 極座標では、点は次の 2 つの数値によって特徴付けます。

  • その大きさは、原点からの点の距離 (つまり、0,0、または x 軸と y 軸が交差する点) です。
  • その位相は、実軸と原点から点に描画された線の間の角度です。

複素数をインスタンス化する

次のいずれかの方法で、複素数に値を割り当てることができます。

  • コンストラクターに 2 つの Double 値を渡すこと。 最初の値は複素数の実数部分を表し、2 番目の値はその虚数部を表します。 これらの値は、2 次元デカルト座標系における複素数の位置を表します。

  • 静的メソッド (Visual Basic では Shared ) を呼び出 Complex.FromPolarCoordinates 、極座標から複素数を作成します。

  • ByteSByteInt16UInt16Int32UInt32Int64UInt64Single、またはDoubleの値をComplex オブジェクトに割り当てます。 この値は複素数の実数部分になり、虚数部は 0 になります。

  • (C# で) キャストするか、(Visual Basic で) Decimal または BigInteger 値を Complex オブジェクトに変換します。 この値は複素数の実数部分になり、虚数部は 0 になります。

  • メソッドまたは演算子によって返される複素数を Complex オブジェクトに割り当てます。 たとえば、 Complex.Add は 2 つの複素数の合計である複素数を返す静的メソッドで、 Complex.Addition 演算子は 2 つの複素数を加算して結果を返します。

次の例は、複素数に値を割り当てる 5 つの方法をそれぞれ示しています。

using System;
using System.Numerics;

public class CreateEx
{
    public static void Main()
    {
        // Create a complex number by calling its class constructor.
        Complex c1 = new Complex(12, 6);
        Console.WriteLine(c1);

        // Assign a Double to a complex number.
        Complex c2 = 3.14;
        Console.WriteLine(c2);

        // Cast a Decimal to a complex number.
        Complex c3 = (Complex)12.3m;
        Console.WriteLine(c3);

        // Assign the return value of a method to a Complex variable.
        Complex c4 = Complex.Pow(Complex.One, -1);
        Console.WriteLine(c4);

        // Assign the value returned by an operator to a Complex variable.
        Complex c5 = Complex.One + Complex.One;
        Console.WriteLine(c5);

        // Instantiate a complex number from its polar coordinates.
        Complex c6 = Complex.FromPolarCoordinates(10, .524);
        Console.WriteLine(c6);
    }
}
// The example displays the following output:
//       (12, 6)
//       (3.14, 0)
//       (12.3, 0)
//       (1, 0)
//       (2, 0)
//       (8.65824721882145, 5.00347430269914)
Imports System.Numerics

Module Example
   Public Sub Main()
      ' Create a complex number by calling its class constructor.
      Dim c1 As New Complex(12, 6)
      Console.WriteLine(c1)
      
      ' Assign a Double to a complex number.
      Dim c2 As Complex = 3.14
      Console.WriteLine(c2)
      
      ' Cast a Decimal to a complex number.
      Dim c3 As Complex = CType(12.3d, Complex)
      Console.WriteLine(c3)
      
      ' Assign the return value of a method to a Complex variable.
      Dim c4 As Complex = Complex.Pow(Complex.One, -1)
      Console.WriteLine(c4)
      
      ' Assign the value returned by an operator to a Complex variable.
      Dim c5 As Complex = Complex.One + Complex.One
      Console.WriteLine(c5)

      ' Instantiate a complex number from its polar coordinates.
      Dim c6 As Complex = Complex.FromPolarCoordinates(10, .524)
      Console.WriteLine(c6)
   End Sub
End Module
' The example displays the following output:
'       (12, 6)
'       (3.14, 0)
'       (12.3000001907349, 0)
'       (1, 0)
'       (2, 0)
'       (8.65824721882145, 5.00347430269914)

複素数を含む操作

.NET の Complex 構造体には、次の機能を提供するメンバーが含まれています。

  • 2 つの複素数を比較して等しいかどうかを判断するメソッド。
  • 複素数に対して算術演算を実行する演算子。 Complex 演算子を使用すると、複素数で加算、減算、乗算、除算、単項否定を実行できます。
  • 複素数に対して他の数値演算を実行するメソッド。 4 つの基本的な算術演算に加えて、指定した累乗に複素数を発生させ、複素数の平方根を見つけ、複素数の絶対値を取得することができます。
  • 複素数に対して三角関数演算を実行するメソッド。 たとえば、複素数で表される角度のタンジェントを計算できます。

Realプロパティと Imaginary プロパティは読み取り専用であるため、既存のComplex オブジェクトの値を変更することはできません。 戻り値がComplex型の場合、Complex番号に対して操作を実行するすべてのメソッドは、新しいComplex番号を返します。

有効桁数と複素数

複素数の実数部分と虚数部は、2 つの倍精度浮動小数点値で表されます。 つまり、倍精度浮動小数点値のような Complex 値は、数値演算の結果として精度を失う可能性があります。 つまり、2 つの値の差が精度の低下による場合でも、2 つの Complex 値の等価性に対する厳密な比較が失敗する可能性があります。 詳細については、Doubleを参照してください。

たとえば、数値の対数に対して指数を実行すると、元の数値が返されます。 ただし、次の例に示すように、浮動小数点値の精度が失われると、2 つの値の間にわずかな違いが生じる場合があります。

Complex value = new Complex(Double.MinValue / 2, Double.MinValue / 2);
Complex value2 = Complex.Exp(Complex.Log(value));
Console.WriteLine("{0} \n{1} \nEqual: {2}", value, value2,
                                            value == value2);
// The example displays the following output:
//    (-8.98846567431158E+307, -8.98846567431158E+307)
//    (-8.98846567431161E+307, -8.98846567431161E+307)
//    Equal: False
Dim value As New Complex(Double.MinValue / 2, Double.MinValue / 2)
Dim value2 As Complex = Complex.Exp(Complex.Log(value))
Console.WriteLine("{0} {3}{1} {3}Equal: {2}", value, value2,
                                              value = value2,
                                              vbCrLf)
' The example displays the following output:
'    (-8.98846567431158E+307, -8.98846567431158E+307)
'    (-8.98846567431161E+307, -8.98846567431161E+307)
'    Equal: False

同様に、次の例では、 Complex 数の平方根を計算し、.NET の 32 ビットバージョンと IA64 バージョンで若干異なる結果を生成します。

Complex minusOne = new Complex(-1, 0);
Console.WriteLine(Complex.Sqrt(minusOne));
// The example displays the following output:
//    (6.12303176911189E-17, 1) on 32-bit systems.
//    (6.12323399573677E-17,1) on IA64 systems.
Dim minusOne As New Complex(-1, 0)
Console.WriteLine(Complex.Sqrt(minusOne))
' The example displays the following output:
'    (6.12303176911189E-17, 1) on 32-bit systems.
'    (6.12323399573677E-17,1) on IA64 systems.

無限大と NaN

複素数の実数部分と虚数部は、 Double 値で表されます。 Double.MinValueからDouble.MaxValueまでの範囲に加えて、複素数の実数または虚数部分には、Double.PositiveInfinityDouble.NegativeInfinity、またはDouble.NaNの値を指定できます。 Double.PositiveInfinityDouble.NegativeInfinity、および Double.NaN はすべて、算術演算または三角関数演算で伝達されます。

次の例では、 Zero で除算すると、実数部と虚数部の両方が Double.NaN複素数が生成されます。 その結果、この値で乗算を実行すると、実数部と虚数部が Double.NaN複素数も生成されます。 同様に、 Double 型の範囲をオーバーフローする乗算を実行すると、実数部分が Double.NaN で虚数部が Double.PositiveInfinity複素数が生成されます。 その後、この複素数で除算を実行すると、実数部が Double.NaN で虚数部が Double.PositiveInfinity複素数が返されます。

using System;
using System.Numerics;

public class NaNEx
{
    public static void Main()
    {
        Complex c1 = new Complex(Double.MaxValue / 2, Double.MaxValue / 2);

        Complex c2 = c1 / Complex.Zero;
        Console.WriteLine(c2.ToString());
        c2 = c2 * new Complex(1.5, 1.5);
        Console.WriteLine(c2.ToString());
        Console.WriteLine();

        Complex c3 = c1 * new Complex(2.5, 3.5);
        Console.WriteLine(c3.ToString());
        c3 = c3 + new Complex(Double.MinValue / 2, Double.MaxValue / 2);
        Console.WriteLine(c3);
    }
}
// The example displays the following output:
//       (NaN, NaN)
//       (NaN, NaN)
//       (NaN, Infinity)
//       (NaN, Infinity)
Imports System.Numerics

Module Example4
    Public Sub Main()
        Dim c1 As Complex = New Complex(Double.MaxValue / 2, Double.MaxValue / 2)

        Dim c2 As Complex = c1 / Complex.Zero
        Console.WriteLine(c2.ToString())
        c2 = c2 * New Complex(1.5, 1.5)
        Console.WriteLine(c2.ToString())
        Console.WriteLine()

        Dim c3 As Complex = c1 * New Complex(2.5, 3.5)
        Console.WriteLine(c3.ToString())
        c3 = c3 + New Complex(Double.MinValue / 2, Double.MaxValue / 2)
        Console.WriteLine(c3)
    End Sub
End Module
' The example displays the following output:
'       (NaN, NaN)
'       (NaN, NaN)
'
'       (NaN, Infinity)
'       (NaN, Infinity)

無効な複素数または Double データ型の範囲をオーバーフローする算術演算では、例外はスローされません。 代わりに、次の条件下で Double.PositiveInfinityDouble.NegativeInfinity、または Double.NaN を返します。

これは、メソッドによって実行されるすべての中間計算に適用されることに注意してください。 たとえば、 new Complex(9e308, 9e308) and new Complex(2.5, 3.5) の乗算では、式 (ac - bd) + (ad + bc)i が使用されます。 乗算の結果として得た実数成分の計算では、式 9e308 2.5 - 9e308 3.5 が評価されます。 この式の各中間乗算はDouble.PositiveInfinityを返し、Double.PositiveInfinityからDouble.PositiveInfinityを減算しようとするとDouble.NaNが返されます。

複素数の書式を設定する

既定では、複素数の文字列表現は (real, imaginary) 形式になります。ここで、 realimaginary は、複素数の実数と虚数の構成要素を形成する Double 値の文字列表現です。 ToString メソッドのオーバーロードによっては、これらのDouble値の文字列表現をカスタマイズして、特定のカルチャの書式設定規則を反映したり、標準またはカスタムの数値書式指定文字列で定義された特定の形式で表示したりできます。 (詳細については、 を参照してください。標準の数値書式指定文字列 および Custom 数値書式指定文字列)。

複素数の文字列表現を表すより一般的な方法の 1 つは、a + bi という形式になります。ここで、a は複素数の実数成分、b は複素数の虚数成分です。 電気工学では、複素数は+bjとして最も一般的に表されます。 複素数の文字列表現は、これら 2 つの形式のいずれかで返すことができます。 これを行うには、 ICustomFormatter インターフェイスと IFormatProvider インターフェイスを実装してカスタム形式プロバイダーを定義し、 String.Format(IFormatProvider, String, Object[]) メソッドを呼び出します。

次の例では、複素数を文字列として表す ComplexFormatter クラスを、+bi または + bj のいずれかの形式で定義します。

using System;
using System.Numerics;

public class ComplexFormatter : IFormatProvider, ICustomFormatter
{
    public object GetFormat(Type formatType)
    {
        if (formatType == typeof(ICustomFormatter))
            return this;
        else
            return null;
    }

    public string Format(string format, object arg,
                         IFormatProvider provider)
    {
        if (arg is Complex)
        {
            Complex c1 = (Complex)arg;
            // Check if the format string has a precision specifier.
            int precision;
            string fmtString = String.Empty;
            if (format.Length > 1)
            {
                try
                {
                    precision = Int32.Parse(format.Substring(1));
                }
                catch (FormatException)
                {
                    precision = 0;
                }
                fmtString = "N" + precision.ToString();
            }
            if (format.Substring(0, 1).Equals("I", StringComparison.OrdinalIgnoreCase))
                return c1.Real.ToString(fmtString) + " + " + c1.Imaginary.ToString(fmtString) + "i";
            else if (format.Substring(0, 1).Equals("J", StringComparison.OrdinalIgnoreCase))
                return c1.Real.ToString(fmtString) + " + " + c1.Imaginary.ToString(fmtString) + "j";
            else
                return c1.ToString(format, provider);
        }
        else
        {
            if (arg is IFormattable)
                return ((IFormattable)arg).ToString(format, provider);
            else if (arg != null)
                return arg.ToString();
            else
                return String.Empty;
        }
    }
}
Imports System.Numerics

Public Class ComplexFormatter
    Implements IFormatProvider, ICustomFormatter

    Public Function GetFormat(formatType As Type) As Object _
                    Implements IFormatProvider.GetFormat
        If formatType Is GetType(ICustomFormatter) Then
            Return Me
        Else
            Return Nothing
        End If
    End Function

    Public Function Format(fmt As String, arg As Object,
                           provider As IFormatProvider) As String _
                    Implements ICustomFormatter.Format
        If TypeOf arg Is Complex Then
            Dim c1 As Complex = DirectCast(arg, Complex)
            ' Check if the format string has a precision specifier.
            Dim precision As Integer
            Dim fmtString As String = String.Empty
            If fmt.Length > 1 Then
                Try
                    precision = Int32.Parse(fmt.Substring(1))
                Catch e As FormatException
                    precision = 0
                End Try
                fmtString = "N" + precision.ToString()
            End If
            If fmt.Substring(0, 1).Equals("I", StringComparison.OrdinalIgnoreCase) Then
                Return c1.Real.ToString(fmtString) + " + " + c1.Imaginary.ToString(fmtString) + "i"
            ElseIf fmt.Substring(0, 1).Equals("J", StringComparison.OrdinalIgnoreCase) Then
                Return c1.Real.ToString(fmtString) + " + " + c1.Imaginary.ToString(fmtString) + "j"
            Else
                Return c1.ToString(fmt, provider)
            End If
        Else
            If TypeOf arg Is IFormattable Then
                Return DirectCast(arg, IFormattable).ToString(fmt, provider)
            ElseIf arg IsNot Nothing Then
                Return arg.ToString()
            Else
                Return String.Empty
            End If
        End If
    End Function
End Class

次の例では、このカスタム フォーマッタを使用して、複素数の文字列表現を表示します。

public class CustomFormatEx
{
    public static void Main()
    {
        Complex c1 = new Complex(12.1, 15.4);
        Console.WriteLine("Formatting with ToString():       " +
                          c1.ToString());
        Console.WriteLine("Formatting with ToString(format): " +
                          c1.ToString("N2"));
        Console.WriteLine("Custom formatting with I0:        " +
                          String.Format(new ComplexFormatter(), "{0:I0}", c1));
        Console.WriteLine("Custom formatting with J3:        " +
                          String.Format(new ComplexFormatter(), "{0:J3}", c1));
    }
}
// The example displays the following output:
//    Formatting with ToString():       (12.1, 15.4)
//    Formatting with ToString(format): (12.10, 15.40)
//    Custom formatting with I0:        12 + 15i
//    Custom formatting with J3:        12.100 + 15.400j
Module Example2
    Public Sub Main()
        Dim c1 As Complex = New Complex(12.1, 15.4)
        Console.WriteLine("Formatting with ToString():       " +
                          c1.ToString())
        Console.WriteLine("Formatting with ToString(format): " +
                          c1.ToString("N2"))
        Console.WriteLine("Custom formatting with I0:        " +
                          String.Format(New ComplexFormatter(), "{0:I0}", c1))
        Console.WriteLine("Custom formatting with J3:        " +
                          String.Format(New ComplexFormatter(), "{0:J3}", c1))
    End Sub
End Module
' The example displays the following output:
'    Formatting with ToString():       (12.1, 15.4)
'    Formatting with ToString(format): (12.10, 15.40)
'    Custom formatting with I0:        12 + 15i
'    Custom formatting with J3:        12.100 + 15.400j