Partilhar via


System.Numerics.Estrutura Complexa

Este artigo fornece observações complementares à documentação de referência para esta API.

Um número complexo é um número que compreende uma parte numérica real e uma parte numérica imaginária. Um número complexo z é geralmente escrito na forma z = x + yi, onde x e y são números reais, e i é a unidade imaginária que tem a propriedade i2 = -1. A parte real do número complexo é representada por x, e a parte imaginária do número complexo é representada por y.

O Complex tipo usa o sistema de coordenadas cartesianas (real, imaginário) ao instanciar e manipular números complexos. Um número complexo pode ser representado como um ponto em um sistema de coordenadas bidimensional, que é conhecido como o plano complexo. A parte real do número complexo está posicionada no eixo x (o eixo horizontal), e a parte imaginária está posicionada no eixo y (o eixo vertical).

Qualquer ponto no plano complexo também pode ser expresso com base no seu valor absoluto, usando o sistema de coordenadas polares. Em coordenadas polares, um ponto é caracterizado por dois números:

  • Sua magnitude, que é a distância do ponto da origem (isto é, 0,0, ou o ponto em que o eixo x e o eixo y se cruzam).
  • Sua fase, que é o ângulo entre o eixo real e a linha traçada da origem ao ponto.

Instanciar um número complexo

Você pode atribuir um valor a um número complexo de uma das seguintes maneiras:

  • Ao passar dois Double valores para o seu construtor. O primeiro valor representa a parte real do número complexo, e o segundo valor representa a sua parte imaginária. Estes valores representam a posição do número complexo no sistema de coordenadas cartesianas bidimensionais.

  • Chamando o método estático (Shared no Visual Basic) Complex.FromPolarCoordinates para criar um número complexo a partir de suas coordenadas polares.

  • Atribuindo um Byte, SByte, , Int16, UInt16Int32, UInt32, Int64, UInt64, Single, ou Double valor a um Complex objeto. O valor torna-se a parte real do número complexo, e sua parte imaginária é igual a 0.

  • Fazendo cast (em C#) ou convertendo (em Visual Basic) um valor Decimal ou BigInteger em um objeto Complex. O valor torna-se a parte real do número complexo, e sua parte imaginária é igual a 0.

  • Atribuindo o número complexo que é retornado por um método ou operador a um Complex objeto. Por exemplo, Complex.Add é um método estático que retorna um número complexo que é a soma de dois números complexos, e o Complex.Addition operador adiciona dois números complexos e retorna o resultado.

O exemplo a seguir demonstra cada uma dessas cinco maneiras de atribuir um valor a um número complexo.

using System;
using System.Numerics;

public class CreateEx
{
    public static void Run()
    {
        // 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 Run()
      ' 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)

Operações com números complexos

A Complex estrutura no .NET inclui membros que fornecem a seguinte funcionalidade:

  • Métodos para comparar dois números complexos para determinar se eles são iguais.
  • Operadores para executar operações aritméticas em números complexos. Complex Os operadores permitem que você execute adição, subtração, multiplicação, divisão e negação unária com números complexos.
  • Métodos para realizar outras operações numéricas em números complexos. Além das quatro operações aritméticas básicas, você pode elevar um número complexo a uma potência especificada, encontrar a raiz quadrada de um número complexo e obter o valor absoluto de um número complexo.
  • Métodos para realizar operações trigonométricas em números complexos. Por exemplo, você pode calcular a tangente de um ângulo representado por um número complexo.

Observe que, como as Real propriedades e Imaginary são somente leitura, não é possível modificar o valor de um objeto existente Complex . Todos os métodos que executam uma operação em um Complex número, se seu valor de retorno for do tipo Complex, retornam um novo Complex número.

Precisão e números complexos

As partes real e imaginária de um número complexo são representadas por dois valores de ponto flutuante de precisão dupla. Isso significa que Complex valores, como valores de ponto flutuante de precisão dupla, podem perder precisão como resultado de operações numéricas. Isto significa que comparações rigorosas para a igualdade de dois Complex valores podem falhar, mesmo que a diferença entre os dois valores se deva a uma perda de precisão. Para obter mais informações, veja Double.

Por exemplo, executar exponenciação no logaritmo de um número deve retornar o número original. No entanto, em alguns casos, a perda de precisão dos valores de vírgula flutuante pode causar pequenas diferenças entre os dois valores, como ilustra o exemplo a seguir.

Complex value = new Complex(Double.MinValue / 2, Double.MinValue / 2);
Complex value2 = Complex.Exp(Complex.Log(value));
Console.WriteLine($"{value} \n{value2} \nEqual: {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

Da mesma forma, o exemplo a seguir, que calcula a raiz quadrada de um Complex número, produz resultados ligeiramente diferentes nas versões de 32 bits e IA64 do .NET.

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.

Infinito e NaN

As partes real e imaginária de um número complexo são representadas por Double valores. Além de variar de Double.MinValue a Double.MaxValue, a parte real ou imaginária de um número complexo pode ter um valor de Double.PositiveInfinity, Double.NegativeInfinityou Double.NaN. Double.PositiveInfinity, Double.NegativeInfinitye Double.NaN todos se propagam em qualquer operação aritmética ou trigonométrica.

No exemplo a seguir, a divisão por Zero produz um número complexo cujas partes reais e imaginárias são ambas Double.NaN. Como resultado, realizar a multiplicação com este valor também produz um número complexo cujas partes reais e imaginárias são Double.NaN. Da mesma forma, realizar uma multiplicação que transborda a gama do Double tipo produz um número complexo cuja parte real é Double.NaN e cuja parte imaginária é Double.PositiveInfinity. Subsequentemente, realizar a divisão com este número complexo retorna um número complexo cuja parte real é Double.NaN e cuja parte imaginária é Double.PositiveInfinity.

using System;
using System.Numerics;

public class NaNEx
{
    public static void Run()
    {
        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 Run()
        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)

Operações matemáticas com números complexos que são inválidos ou que excedem o intervalo do tipo de Double dados não lançam uma exceção. Em vez disso, eles retornam um Double.PositiveInfinity, Double.NegativeInfinity, ou Double.NaN sob as seguintes condições:

Observe que isso se aplica a quaisquer cálculos intermediários realizados por um método. Por exemplo, a multiplicação de new Complex(9e308, 9e308) and new Complex(2.5, 3.5) usa a fórmula (ac - bd) + (ad + bc)i. O cálculo do componente real que resulta da multiplicação avalia a expressão 9e308 2,5 - 9e308 3,5. Cada multiplicação intermediária nesta expressão retorna Double.PositiveInfinity, e a tentativa de subtrair Double.PositiveInfinity de Double.PositiveInfinity retorna Double.NaN.

Formatar um número complexo

Por padrão, a representação de cadeia de um número complexo assume a forma realimaginário, onde real e imaginário são as representações de cadeia dos valores que formam os componentes reais e imaginários do número complexo. Algumas sobrecargas do método ToString permitem a personalização das representações em forma de texto desses Double valores para refletir as convenções de formatação de uma cultura específica ou para aparecer num formato específico definido por uma string de formato numérico estandardizado ou personalizado. (Para obter mais informações, consulte Cadeias de caracteres de formato numérico padrão e cadeias de caracteres de formato numérico personalizado.)

Uma das formas mais comuns de expressar a representação em cadeia de um número complexo toma a forma a + bi, onde a é o componente real do número complexo, e b é o componente imaginário do número complexo. Em engenharia elétrica, um número complexo é mais comumente expresso como a + bj. Você pode retornar a representação de cadeia de caracteres de um número complexo em qualquer uma dessas duas formas. Para fazer isso, defina um provedor de formato personalizado implementando as ICustomFormatter interfaces e IFormatProvider e, em seguida, chame o String.Format(IFormatProvider, String, Object[]) método.

O exemplo a seguir define uma ComplexFormatter classe que representa um número complexo como uma cadeia de caracteres na forma de um a + bi ou a + 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 c1)
        {
            // Check if the format string has a precision specifier.
            int precision;
            string fmtString = string.Empty;
            if (format.Length > 1)
            {
                try
                {
                    precision = int.Parse(format.Substring(1));
                }
                catch (FormatException)
                {
                    precision = 0;
                }
                fmtString = "N" + precision.ToString();
            }
            if (format.Substring(0, 1).Equals("I", StringComparison.OrdinalIgnoreCase))
            {
                // Determine the sign to display.
                char sign = c1.Imaginary < 0 ? '-' : '+';
                // Display the determined sign and the absolute value of the imaginary part.
                return c1.Real.ToString(fmtString) + " " + sign + " " + Math.Abs(c1.Imaginary).ToString(fmtString) + "i";
            }
            else if (format.Substring(0, 1).Equals("J", StringComparison.OrdinalIgnoreCase))
            {
                // Determine the sign to display.
                char sign = c1.Imaginary < 0 ? '-' : '+';
                // Display the determined sign and the absolute value of the imaginary part.
                return c1.Real.ToString(fmtString) + " " + sign + " " + Math.Abs(c1.Imaginary).ToString(fmtString) + "j";
            }
            else
                return c1.ToString(format, provider);
        }
        else
        {
            if (arg is IFormattable formattable)
                return formattable.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 = Integer.Parse(fmt.Substring(1))
                Catch e As FormatException
                    precision = 0
                End Try
                fmtString = "N" + precision.ToString()
            End If
            ' Determine the sign to display.
            Dim sign As Char = If(c1.Imaginary < 0.0, "-"c, "+"c)
            ' Display the determined sign and the absolute value of the imaginary part.
            If fmt.Substring(0, 1).Equals("I", StringComparison.OrdinalIgnoreCase) Then
                Return c1.Real.ToString(fmtString) + " " + sign + " " + Math.Abs(c1.Imaginary).ToString(fmtString) + "i"
            ElseIf fmt.Substring(0, 1).Equals("J", StringComparison.OrdinalIgnoreCase) Then
                Return c1.Real.ToString(fmtString) + " " + sign + " " + Math.Abs(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

O exemplo a seguir usa esse formatador personalizado para exibir a representação de cadeia de caracteres de um número complexo.

public class CustomFormatEx
{
    public static void Run()
    {
        Complex c1 = new(12.1, 15.4);
        Console.WriteLine($"Formatting with ToString:         {c1}");
        Console.WriteLine($"Formatting with ToString(format): {c1:N2}");
        Console.WriteLine($"Custom formatting with I0:\t" +
            $"  {string.Format(new ComplexFormatter(), "{0:I0}", c1)}");
        Console.WriteLine($"Custom formatting with J3:\t" +
            $"  {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 Run()
        Dim c1 As New Complex(12.1, 15.4)
        Console.WriteLine($"Formatting with ToString():       {c1}")
        Console.WriteLine($"Formatting with ToString(format): {c1: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