Exportar (0) Imprimir
Expandir Tudo
Este artigo foi traduzido por máquina. Coloque o ponteiro do mouse sobre as frases do artigo para ver o texto original. Mais informações.
Tradução
Original

Estrutura Double

Representa um número de ponto flutuante de precisão dupla.

Namespace:  System
Assembly:  mscorlib (em mscorlib.dll)

[SerializableAttribute]
[ComVisibleAttribute(true)]
public struct Double : IComparable, IFormattable, 
	IConvertible, IComparable<double>, IEquatable<double>

O tipo Double expõe os membros a seguir.

  NomeDescrição
Método públicoCompatível com o XNA FrameworkCom suporte por Biblioteca de Classes PortátilCom suporte em .NET para aplicativos da Windows StoreCompareTo(Double)Compara esta instância em um número de ponto flutuante de precisão dupla especificado e retorna um inteiro que indica se o valor desta instância for menor que, igual ou maior que o valor de número de ponto flutuante de precisão dupla especificado.
Método públicoCompatível com o XNA FrameworkCompareTo(Object)Compara esta instância em um objeto especificado e retorna um inteiro que indica se o valor desta instância for menor que, igual ou maior que o valor do objeto especificado.
Método públicoCompatível com o XNA FrameworkCom suporte por Biblioteca de Classes PortátilCom suporte em .NET para aplicativos da Windows StoreEquals(Double)Retorna um valor que indica se essa instância e um objeto especificado de Double representam o mesmo valor.
Método públicoCompatível com o XNA FrameworkCom suporte por Biblioteca de Classes PortátilCom suporte em .NET para aplicativos da Windows StoreEquals(Object)Retorna um valor que indica se essa instância é igual a um objeto especificado. (Substitui ValueType.Equals(Object).)
Método públicoCompatível com o XNA FrameworkCom suporte por Biblioteca de Classes PortátilCom suporte em .NET para aplicativos da Windows StoreGetHashCode Retorna o hash code para essa instância. (Substitui ValueType.GetHashCode().)
Método públicoCompatível com o XNA FrameworkCom suporte por Biblioteca de Classes PortátilCom suporte em .NET para aplicativos da Windows StoreGetType Obtém o Type da instância atual. (Herdado de Object.)
Método públicoCompatível com o XNA FrameworkGetTypeCodeRetorna TypeCode para o tipo de valor Double.
Método públicoMembro estáticoCompatível com o XNA FrameworkCom suporte por Biblioteca de Classes PortátilCom suporte em .NET para aplicativos da Windows StoreIsInfinityRetorna um valor que indica se o número especificado avaliar ao infinito negativo ou positivo
Método públicoMembro estáticoCompatível com o XNA FrameworkCom suporte por Biblioteca de Classes PortátilCom suporte em .NET para aplicativos da Windows StoreIsNaNRetorna um valor que indica se o valor especificado não é um número (NaN).
Método públicoMembro estáticoCompatível com o XNA FrameworkCom suporte por Biblioteca de Classes PortátilCom suporte em .NET para aplicativos da Windows StoreIsNegativeInfinityRetorna um valor que indica se o número especificado avaliar ao infinito negativo.
Método públicoMembro estáticoCompatível com o XNA FrameworkCom suporte por Biblioteca de Classes PortátilCom suporte em .NET para aplicativos da Windows StoreIsPositiveInfinityRetorna um valor que indica se o número especificado avaliar ao infinito positivo.
Método públicoMembro estáticoCompatível com o XNA FrameworkCom suporte por Biblioteca de Classes PortátilCom suporte em .NET para aplicativos da Windows StoreParse(String)Converte a representação da cadeia de caracteres de um número no equivalente do número de ponto flutuante de precisão dupla.
Método públicoMembro estáticoCompatível com o XNA FrameworkCom suporte por Biblioteca de Classes PortátilCom suporte em .NET para aplicativos da Windows StoreParse(String, NumberStyles)Converte a representação de cadeia de caracteres de um número em um estilo especificado para seu equivalente de precisão dupla de número de ponto flutuante.
Método públicoMembro estáticoCompatível com o XNA FrameworkCom suporte por Biblioteca de Classes PortátilCom suporte em .NET para aplicativos da Windows StoreParse(String, IFormatProvider)Converte a representação de cadeia de caracteres de um número em um formato específico a cultura especificado para seu equivalente de precisão dupla de número de ponto flutuante.
Método públicoMembro estáticoCompatível com o XNA FrameworkCom suporte por Biblioteca de Classes PortátilCom suporte em .NET para aplicativos da Windows StoreParse(String, NumberStyles, IFormatProvider)Converte a representação de cadeia de caracteres de um número em um estilo especificado e a cultura de formato específico para seu equivalente de precisão dupla de número de ponto flutuante.
Método públicoCompatível com o XNA FrameworkCom suporte por Biblioteca de Classes PortátilCom suporte em .NET para aplicativos da Windows StoreToString()Converte o valor numérico dessa instância na representação da cadeia de caracteres equivalente. (Substitui ValueType.ToString().)
Método públicoCompatível com o XNA FrameworkCom suporte por Biblioteca de Classes PortátilCom suporte em .NET para aplicativos da Windows StoreToString(IFormatProvider)Converte o valor numérico dessa instância na representação da cadeia de caracteres equivalente usando as informações de formato específicas da cultura especificada.
Método públicoCompatível com o XNA FrameworkCom suporte por Biblioteca de Classes PortátilCom suporte em .NET para aplicativos da Windows StoreToString(String)Converte o valor numérico dessa instância na representação da cadeia de caracteres equivalente usando o formato especificado.
Método públicoCompatível com o XNA FrameworkCom suporte por Biblioteca de Classes PortátilCom suporte em .NET para aplicativos da Windows StoreToString(String, IFormatProvider)Converte o valor numérico dessa instância na representação da cadeia de caracteres equivalente usando o formato especificado e as informações de formato específicas da cultura especificada.
Método públicoMembro estáticoCom suporte por Biblioteca de Classes PortátilCom suporte em .NET para aplicativos da Windows StoreTryParse(String, Double)Converte a representação da cadeia de caracteres de um número no equivalente do número de ponto flutuante de precisão dupla. Um valor de retorno indica se a conversão foi bem-sucedida ou falhou.
Método públicoMembro estáticoCom suporte por Biblioteca de Classes PortátilCom suporte em .NET para aplicativos da Windows StoreTryParse(String, NumberStyles, IFormatProvider, Double)Converte a representação de cadeia de caracteres de um número em um estilo especificado e a cultura de formato específico para seu equivalente de precisão dupla de número de ponto flutuante. Um valor de retorno indica se a conversão foi bem-sucedida ou falhou.
Superior

  NomeDescrição
Operador públicoMembro estáticoCom suporte por Biblioteca de Classes PortátilCom suporte em .NET para aplicativos da Windows StoreEqualityRetorna um valor que indica se dois valores especificados de Double são iguais.
Operador públicoMembro estáticoCom suporte por Biblioteca de Classes PortátilCom suporte em .NET para aplicativos da Windows StoreGreaterThanRetorna um valor que indica se um valor especificado de Double é maior que outro valor especificado de Double .
Operador públicoMembro estáticoCom suporte por Biblioteca de Classes PortátilCom suporte em .NET para aplicativos da Windows StoreGreaterThanOrEqualRetorna um valor que indica se um valor especificado de Double é maior ou igual a outro valor especificado de Double .
Operador públicoMembro estáticoCom suporte por Biblioteca de Classes PortátilCom suporte em .NET para aplicativos da Windows StoreInequalityRetorna um valor que indica se dois valores especificados de Double não são iguais.
Operador públicoMembro estáticoCom suporte por Biblioteca de Classes PortátilCom suporte em .NET para aplicativos da Windows StoreLessThanRetorna um valor que indica se um valor especificado de Double é menor que outro valor especificado de Double .
Operador públicoMembro estáticoCom suporte por Biblioteca de Classes PortátilCom suporte em .NET para aplicativos da Windows StoreLessThanOrEqualRetorna um valor que indica se um valor especificado de Double é menor ou igual a outro valor especificado de Double .
Superior

  NomeDescrição
Campo públicoMembro estáticoCompatível com o XNA FrameworkCom suporte por Biblioteca de Classes PortátilCom suporte em .NET para aplicativos da Windows StoreEpsilonRepresenta o valor positivo o menor de Double que for maior que zero. Este campo é constante.
Campo públicoMembro estáticoCompatível com o XNA FrameworkCom suporte por Biblioteca de Classes PortátilCom suporte em .NET para aplicativos da Windows StoreMaxValueRepresenta o maior valor possível de Double. Este campo é constante.
Campo públicoMembro estáticoCompatível com o XNA FrameworkCom suporte por Biblioteca de Classes PortátilCom suporte em .NET para aplicativos da Windows StoreMinValueRepresenta o valor possível o menor de Double. Este campo é constante.
Campo públicoMembro estáticoCompatível com o XNA FrameworkCom suporte por Biblioteca de Classes PortátilCom suporte em .NET para aplicativos da Windows StoreNaNRepresenta um valor que não é um número (NaN). Este campo é constante.
Campo públicoMembro estáticoCompatível com o XNA FrameworkCom suporte por Biblioteca de Classes PortátilCom suporte em .NET para aplicativos da Windows StoreNegativeInfinityRepresenta o infinito negativo. Este campo é constante.
Campo públicoMembro estáticoCompatível com o XNA FrameworkCom suporte por Biblioteca de Classes PortátilCom suporte em .NET para aplicativos da Windows StorePositiveInfinityRepresenta o infinito positivo. Este campo é constante.
Superior

  NomeDescrição
Implementação explícita da interfaceMétodo particularCom suporte por Biblioteca de Classes PortátilCom suporte em .NET para aplicativos da Windows StoreIComparable.CompareToCompara a instância atual com outro objeto do mesmo tipo e retorna um inteiro que indica se a instância atual precede, segue ou ocorre na mesma posição da ordem de classificação do outro objeto.
Implementação explícita da interfaceMétodo particularCompatível com o XNA FrameworkIConvertible.ToBooleanInfraestrutura. Para obter uma descrição desse membro, consulte IConvertible.ToBoolean.
Implementação explícita da interfaceMétodo particularCompatível com o XNA FrameworkIConvertible.ToByteInfraestrutura. Para obter uma descrição desse membro, consulte IConvertible.ToByte.
Implementação explícita da interfaceMétodo particularCompatível com o XNA FrameworkIConvertible.ToCharInfraestrutura. Esta conversão não é suportada. A tentativa de usar esse método lança um InvalidCastException.
Implementação explícita da interfaceMétodo particularCompatível com o XNA FrameworkIConvertible.ToDateTimeInfraestrutura. Esta conversão não é suportada. Tentar usar esse método lançará InvalidCastException
Implementação explícita da interfaceMétodo particularCompatível com o XNA FrameworkIConvertible.ToDecimalInfraestrutura. Para obter uma descrição desse membro, consulte IConvertible.ToDecimal.
Implementação explícita da interfaceMétodo particularCompatível com o XNA FrameworkIConvertible.ToDoubleInfraestrutura. Para obter uma descrição desse membro, consulte IConvertible.ToDouble.
Implementação explícita da interfaceMétodo particularCompatível com o XNA FrameworkIConvertible.ToInt16Infraestrutura. Para obter uma descrição desse membro, consulte IConvertible.ToInt16.
Implementação explícita da interfaceMétodo particularCompatível com o XNA FrameworkIConvertible.ToInt32Infraestrutura. Para obter uma descrição desse membro, consulte IConvertible.ToInt32.
Implementação explícita da interfaceMétodo particularCompatível com o XNA FrameworkIConvertible.ToInt64Infraestrutura. Para obter uma descrição desse membro, consulte IConvertible.ToInt64.
Implementação explícita da interfaceMétodo particularCompatível com o XNA FrameworkIConvertible.ToSByteInfraestrutura. Para obter uma descrição desse membro, consulte IConvertible.ToSByte.
Implementação explícita da interfaceMétodo particularCompatível com o XNA FrameworkIConvertible.ToSingleInfraestrutura. Para obter uma descrição desse membro, consulte IConvertible.ToSingle.
Implementação explícita da interfaceMétodo particularCompatível com o XNA FrameworkIConvertible.ToTypeInfraestrutura. Para obter uma descrição desse membro, consulte IConvertible.ToType.
Implementação explícita da interfaceMétodo particularCompatível com o XNA FrameworkIConvertible.ToUInt16Infraestrutura. Para obter uma descrição desse membro, consulte IConvertible.ToUInt16.
Implementação explícita da interfaceMétodo particularCompatível com o XNA FrameworkIConvertible.ToUInt32Infraestrutura. Para obter uma descrição desse membro, consulte IConvertible.ToUInt32.
Implementação explícita da interfaceMétodo particularCompatível com o XNA FrameworkIConvertible.ToUInt64Infraestrutura. Para obter uma descrição desse membro, consulte IConvertible.ToUInt64.
Superior

O tipo de valor de Double representa um número de 64 bits de precisão dupla com valores que variam de 1.79769313486232e308 negativo a 1.79769313486232e308 positivo, bem como positivos ou negativos zero, PositiveInfinity, NegativeInfinity, e não um número (NaN). O objetivo de representar valores que são extremamente grandes (como distâncias entre planetas ou galáxias) ou extremamente pequeno (a molecular massa de uma substância em quilogramas) e que são frequentemente imprecisas (como a distância da terra para outro sistema solar), o tipo de Double está em conformidade com o padrão de 60559:1989 de IEC (IEEE 754) para aritmética de ponto flutuante binário.

Este tópico consiste nas seguintes seções:

Representação de ponto flutuante e precisão

O tipo de dados de Double armazena valores de ponto flutuante de precisão dupla em um formato binário de 64 bits, conforme mostrado na seguinte tabela:

Parte

Bit

Significand ou mantissa

0-51

Expoente

52-62

0 = (Sinal positivo, 1 = negativo)

63

Assim como as frações decimais não conseguirão se representar precisamente alguns valores fracionários (como 1/3 ou Math.PI), as frações binários não conseguirão se representar alguns valores fracionários. Por exemplo, 1/10, que é representado por precisamente .1 como uma fração decimal, são representados por .001100110011 como uma fração binário, com o padrão “0011 " repetindo ao infinito. Nesse caso, o valor de ponto flutuante fornece uma representação imprecisa o número que representa. Executar operações matemáticas adicionais no valor de ponto flutuante original geralmente tende a aumentar a falta de precisão. Por exemplo, se nós comparamos o resultado de multiplicar .1 por 10 e adicionar .1 a .1 nove vezes, é vemos que a adição, porque envolver mais de oito operações, geramos o resultado menos precisas. Observe que essa disparidade estão aparentes somente se nós exibimos os dois valores de Double usando o “R” cadeia de caracteres de formatação numérica padrãose necessário, que exibe todos os 17 dígitos de precisão suporte do tipo de Double .


using System;

public class Example
{
   public static void Main()
   {
      Double value = .1;
      Double result1 = value * 10;
      Double result2 = 0;
      for (int ctr = 1; ctr <= 10; ctr++)
         result2 += value;

      Console.WriteLine(".1 * 10:           {0:R}", result1);
      Console.WriteLine(".1 Added 10 times: {0:R}", result2);
   }
}
// The example displays the following output:
//       .1 * 10:           1
//       .1 Added 10 times: 0.99999999999999989


Como alguns números não podem ser representados exatamente como valores binários fracionários, os números de pontos flutuantes podem ver apenas números reais.

Todos os números de pontos flutuantes também têm um número limitado de dígitos significativos, que também determina como exatamente um valor de ponto flutuante aproxima um número real. Um valor de Double contendo até 15 dígitos decimais de precisão, embora um máximo de 17 dígitos seja mantido interiormente. Isso significa que algumas operações de ponto flutuante podem não ter a precisão para alterar um valor de ponto flutuante. O exemplo a seguir fornece uma ilustração. Define um valor de ponto flutuante muito grande, e adiciona o produto de Double.Epsilon e um quadrillion. O produto, porém, é muito pequeno alterar o valor de ponto flutuante original. O menos dígito significante é milésimos, enquanto o dígito o mais significativo sobre o produto é 1.-312


using System;

public class Example
{
   public static void Main()
   {
      Double value = 123456789012.34567;
      Double additional = Double.Epsilon * 1e12;
      Console.WriteLine("{0} + {1} = {2}", value, additional, 
                                           value + additional);
   }
}
// The example displays the following output:
//    123456789012.346 + 4.94065645841247E-312 = 123456789012.346


A precisão limitada de um número de ponto flutuante tem várias consequências:

  • Dois números de ponto flutuante que pareçam iguais para uma determinada precisão podem não ser comparados como iguais porque seus dígitos menos significantes são diferentes. No exemplo, uma série de números são unidas, e o total é comparado com o total esperado. Embora os dois valores pareçam ser os mesmos, uma chamada ao método de Equals indica que não são.

    
    using System;
    
    public class Example
    {
       public static void Main()
       {
          Double[] values = { 10.0, 2.88, 2.88, 2.88, 9.0 };
          Double result = 27.64;
          Double total = 0;
          foreach (var value in values)
             total += value;
    
          if (total.Equals(result))
             Console.WriteLine("The sum of the values equals the total.");
          else
             Console.WriteLine("The sum of the values ({0}) does not equal the total ({1}).",
                               total, result); 
       }
    }
    // The example displays the following output:
    //      The sum of the values (36.64) does not equal the total (36.64).   
    //
    // If the index items in the Console.WriteLine statement are changed to {0:R},
    // the example displays the following output:
    //       The sum of the values (27.639999999999997) does not equal the total (27.64).   
    
    
    

    Se você alterar os itens de formato na instrução de Console.WriteLine(String, Object, Object) de {0} e de {1} a {0:R} e a {1:R} para exibir todos os dígitos significativos dos dois valores de Double , é claro que os dois valores são diferentes devido à perda de precisão durante as operações de adição. Nesse caso, o problema pode ser resolvido chamando o método de Math.Round(Double, Int32) para arredondar os valores de Double à precisão desejada antes de executar a comparação.

  • Uma operação matemática ou de comparação que use um número de ponto flutuante talvez não produza o mesmo resultado se um número decimal for usado, como o número de ponto flutuante binário não pode ser igual ao número decimal. Um exemplo anterior ilustrou este exibindo o resultado de multiplicar .1 por 10 e adicionar .1 vez.

    Quando a precisão em operações numéricas com os valores fracionários é importante, você pode usar Decimal em vez do tipo de Double . Quando a precisão em operações numéricas com os valores integrais além do intervalo dos tipos de Int64 ou de UInt64 é importante, use o tipo de BigInteger .

  • Um valor não pode viagem de ida e volta se um número de ponto flutuante estiver envolvido. Um valor é considerado como a viagem de ida e volta se uma operação converte um número de ponto flutuante original para outra forma, uma operação inversa transforma a forma convertida novamente a um número de ponto flutuante, e o número de ponto flutuante final não é igual ao número de ponto flutuante original. A viagem de ida e volta pode falhar porque um ou mais dígitos menos significantes são perdidos ou alterados na conversão. No exemplo, três valores de Double são convertidos em cadeias de caracteres e salvos em um arquivo. Como a saída mostra, porém, mesmo que os valores pareçam ser idênticos, os valores restaurados não forem iguais aos valores originais.

    
    using System;
    using System.IO;
    
    public class Example
    {
       public static void Main()
       {
          StreamWriter sw = new StreamWriter(@".\Doubles.dat");
          Double[] values = { 2.2/1.01, 1.0/3, Math.PI };
          for (int ctr = 0; ctr < values.Length; ctr++) {
             sw.Write(values[ctr].ToString());
             if (ctr != values.Length - 1)
                sw.Write("|");
          }      
          sw.Close();
    
          Double[] restoredValues = new Double[values.Length];
          StreamReader sr = new StreamReader(@".\Doubles.dat");
          string temp = sr.ReadToEnd();
          string[] tempStrings = temp.Split('|');
          for (int ctr = 0; ctr < tempStrings.Length; ctr++)
             restoredValues[ctr] = Double.Parse(tempStrings[ctr]);   
    
    
          for (int ctr = 0; ctr < values.Length; ctr++)
             Console.WriteLine("{0} {2} {1}", values[ctr], 
                               restoredValues[ctr],
                               values[ctr].Equals(restoredValues[ctr]) ? "=" : "<>");
       }
    }
    // The example displays the following output:
    //       2.17821782178218 <> 2.17821782178218
    //       0.333333333333333 <> 0.333333333333333
    //       3.14159265358979 <> 3.14159265358979
    
    
    

    Nesse caso, os valores podem com êxito redonda ser tropeçados usando o “R” cadeia de caracteres de formatação numérica padrão para preservar a precisão completa de valores de Double , conforme mostrado no exemplo a seguir.

    
    using System;
    using System.IO;
    
    public class Example
    {
       public static void Main()
       {
          StreamWriter sw = new StreamWriter(@".\Doubles.dat");
          Double[] values = { 2.2/1.01, 1.0/3, Math.PI };
          for (int ctr = 0; ctr < values.Length; ctr++) 
             sw.Write("{0:R}{1}", values[ctr], ctr < values.Length - 1 ? "|" : "" );
    
          sw.Close();
    
          Double[] restoredValues = new Double[values.Length];
          StreamReader sr = new StreamReader(@".\Doubles.dat");
          string temp = sr.ReadToEnd();
          string[] tempStrings = temp.Split('|');
          for (int ctr = 0; ctr < tempStrings.Length; ctr++)
             restoredValues[ctr] = Double.Parse(tempStrings[ctr]);   
    
    
          for (int ctr = 0; ctr < values.Length; ctr++)
             Console.WriteLine("{0} {2} {1}", values[ctr], 
                               restoredValues[ctr],
                               values[ctr].Equals(restoredValues[ctr]) ? "=" : "<>");
       }
    }
    // The example displays the following output:
    //       2.17821782178218 = 2.17821782178218
    //       0.333333333333333 = 0.333333333333333
    //       3.14159265358979 = 3.14159265358979
    
    
    
  • os valores deSingle têm menos precisão dos valores de Double . Um valor de Single que é convertido em Double aparentemente equivalente geralmente não é igual ao valor de Double devido às diferenças na precisão. No exemplo a seguir, o resultado de operações idênticas de divisão é atribuído a Double e um valor de Single . Depois que o valor de Single é convertido em Double, uma comparação dos dois valores mostra que são diferentes.

    
    using System;
    
    public class Example
    {
       public static void Main()
       {
          Double value1 = 1/3.0;
          Single sValue2 = 1/3.0f;
          Double value2 = (Double) sValue2;
          Console.WriteLine("{0:R} = {1:R}: {2}", value1, value2, 
                                              value1.Equals(value2));
       }
    }
    // The example displays the following output:
    //        0.33333333333333331 = 0.3333333432674408: False
    
    
    

    Para evitar esse problema, use Double no lugar do tipo de dados de Single , ou usar o método de Round de modo que ambos os valores têm a mesma precisão.

Além disso, o resultado de aritmética e as operações de atribuição com os valores de Double podem diferir ligeiramente pela plataforma devido à perda de precisão do tipo de Double . Por exemplo, o resultado de atribuir um valor literal de Double pode diferir em versões de 32 bits e de 64 bits do.NET Framework. O exemplo a seguir ilustra a diferença quando o valor literal -4.42330604244772E-305 e uma variável cujo valor é -4.42330604244772E-305 são atribuídos a uma variável de Double . Observe que o resultado do método de Parse(String) nesse caso não sofrê de uma perda de precisão.


double value = -4.42330604244772E-305;

double fromLiteral = -4.42330604244772E-305;
double fromVariable = value;
double fromParse = Double.Parse("-4.42330604244772E-305");

Console.WriteLine("Double value from literal: {0,29:R}", fromLiteral);
Console.WriteLine("Double value from variable: {0,28:R}", fromVariable);
Console.WriteLine("Double value from Parse method: {0,24:R}", fromParse);      
// On 32-bit versions of the .NET Framework, the output is:
//    Double value from literal:        -4.42330604244772E-305
//    Double value from variable:       -4.42330604244772E-305
//    Double value from Parse method:   -4.42330604244772E-305
//
// On other versions of the .NET Framework, the output is:
//    Double value from literal:      -4.4233060424477198E-305
//    Double value from variable:     -4.4233060424477198E-305
//    Double value from Parse method:   -4.42330604244772E-305      


Testando igualdade

Para ser considerado igual, dois valores de Double devem representar valores idênticos. No entanto, devido às diferenças na precisão entre valores, ou devido à perda de precisão por um ou ambos valores, valores de ponto flutuante que devem ser ativar que geralmente idêntico a forma diferente por causa das diferenças em seus dígitos menos significantes. No resultado, as chamadas para o método de Equals para determinar se dois valores são iguais, ou chamadas para o método de CompareTo para determinar a relação entre dois valores de Double , são frequentemente resultados inesperados. Isso é evidente no exemplo a seguir, onde dois valores iguais aparentemente de Double despejam ser diferentes como os primeiros têm 15 dígitos de precisão, quando os segundos têm 17.


using System;

public class Example
{
   public static void Main()
   {
      double value1 = .333333333333333;
      double value2 = 1.0/3;
      Console.WriteLine("{0:R} = {1:R}: {2}", value1, value2, value1.Equals(value2));
   }
}
// The example displays the following output:
//        0.333333333333333 = 0.33333333333333331: False


Os valores calculados que seguem diferentes caminhos de código e que são manipulados de modos diferentes exemplo frequentemente ser diferentes. No exemplo a seguir, um valor de Double é a, e a raiz quadrada é calculada em para restaurar o valor original. Um segundo Double é multiplicado por 3,51 e a antes da raiz quadrada do resultado seja dividido por 3,51 para restaurar o valor original. Embora os dois valores pareçam ser idênticos, uma chamada ao método de Equals(Double) indica que não são iguais. Usando a cadeia de caracteres de formato padrão de “R” para retornar um resultado cadeia de caracteres que exibe todos os dígitos significativos de cada valor duplo mostra que o segundo valor .0000000000001 é menor que o primeiro.


using System;

public class Example
{
   public static void Main()
   {
      double value1 = 100.10142;
      value1 = Math.Sqrt(Math.Pow(value1, 2));
      double value2 = Math.Pow(value1 * 3.51, 2);
      value2 = Math.Sqrt(value2) / 3.51;
      Console.WriteLine("{0} = {1}: {2}\n", 
                        value1, value2, value1.Equals(value2)); 
      Console.WriteLine("{0:R} = {1:R}", value1, value2); 
   }
}
// The example displays the following output:
//    100.10142 = 100.10142: False
//    
//    100.10142 = 100.10141999999999


Nos casos em que uma perda de precisão é provável que afete o resultado de uma comparação, você pode adotar uma das seguintes alternativas para chamar o método de Equals ou de CompareTo :

  • Chame o método de Math.Round para garantir que ambos os valores têm a mesma precisão. O exemplo a seguir altera um exemplo anterior para usar esta abordagem de modo que dois valores fracionários sejam equivalentes.

    
    using System;
    
    public class Example
    {
       public static void Main()
       {
          double value1 = .333333333333333;
          double value2 = 1.0/3;
          int precision = 7;
          value1 = Math.Round(value1, precision);
          value2 = Math.Round(value2, precision);
          Console.WriteLine("{0:R} = {1:R}: {2}", value1, value2, value1.Equals(value2));
       }
    }
    // The example displays the following output:
    //        0.3333333 = 0.3333333: True
    
    
    

    Observe, entretanto, que o problema de precisão ainda aplica a arredondamentos de valores de ponto médio. Para obter mais informações, consulte o método Math.Round(Double, Int32, MidpointRounding).

  • Testar a igualdade aproximada em vez da igualdade. Isso requer que você defina um absoluta a quantidade pela qual os dois valores podem diferir mas ainda para ser iguais, ou que você define uma quantia relativa por que o menor valor pode divergir de valor maior.

    Observação de cuidadoCuidado

    Double.Epsilon às vezes é usado como uma medida de distância absoluta entre dois valores de Double ao testar a igualdade. No entanto, Double.Epsilon ultrapassar o valor possível ao menor que podem ser adicionados, ou ser subtraído de Double , cujo valor é zero. Para os valores mais positivos e negativos dos mais Double , o valor de Double.Epsilon é muito pequeno para ser detectado. Consequentemente, com exceção dos valores que são zero, não recomendamos o uso em testa a igualdade.

    O exemplo a seguir usa a última abordagem para definir um método de IsApproximatelyEqual que testa a diferença relativa entre dois valores. Também contrasta o resultado de chamadas para o método de IsApproximatelyEqual e ao método de Equals(Double) .

    
    using System;
    
    public class Example
    {
       public static void Main()
       {
          double one1 = .1 * 10;
          double one2 = 0;
          for (int ctr = 1; ctr <= 10; ctr++)
             one2 += .1;
    
          Console.WriteLine("{0:R} = {1:R}: {2}", one1, one2, one1.Equals(one2));
          Console.WriteLine("{0:R} is approximately equal to {1:R}: {2}", 
                            one1, one2, 
                            IsApproximatelyEqual(one1, one2, .000000001));   
       }
    
       static bool IsApproximatelyEqual(double value1, double value2, double epsilon)
       {
          // If they are equal anyway, just return True.
          if (value1.Equals(value2))
             return true;
    
          // Handle NaN, Infinity.
          if (Double.IsInfinity(value1) | Double.IsNaN(value1))
             return value1.Equals(value2);
          else if (Double.IsInfinity(value2) | Double.IsNaN(value2))
             return value1.Equals(value2);
    
          // Handle zero to avoid division by zero
          double divisor = Math.Max(value1, value2);
          if (divisor.Equals(0)) 
             divisor = Math.Min(value1, value2);
    
          return Math.Abs(value1 - value2)/divisor <= epsilon;           
       } 
    }
    // The example displays the following output:
    //       1 = 0.99999999999999989: False
    //       1 is approximately equal to 0.99999999999999989: True
    
    
    

Valores de ponto flutuante e exceções

Ao contrário das operações com os tipos integrais, que lançam exceções em casos de estouro ou de operações ilegais como divisão por zero, as operações com os valores de ponto flutuante não lançam exceções. Em vez disso, em casos excepcionais, o resultado de uma operação de ponto flutuante for zero, infinito positivo, infinito negativo, ou não é um número (NaN):

  • Se o resultado de uma operação de ponto flutuante for muito pequeno para o formato de destino, o resultado será nulo. Isso pode ocorrer quando dois números muito pequenos são multiplicados, conforme mostrado no exemplo a seguir.

    
    using System;
    
    public class Example
    {
       public static void Main()
       {
          Double value1 = 1.1632875981534209e-225;
          Double value2 = 9.1642346778e-175;
          Double result = value1 * value2;
          Console.WriteLine("{0} * {1} = {2}", value1, value2, result);
          Console.WriteLine("{0} = 0: {1}", result, result.Equals(0.0));
       }
    }
    // The example displays the following output:
    //       1.16328759815342E-225 * 9.1642346778E-175 = 0
    //       0 = 0: True
    
    
    
  • Se o valor do resultado de uma operação de ponto flutuante excede o intervalo do formato de destino, o resultado da operação é PositiveInfinity ou NegativeInfinity, conforme apropriado para o sinal do resultado. O resultado de uma operação que não Double.MaxValue é PositiveInfinity, e o resultado de uma operação que os estouros Double.MinValue são NegativeInfinity, conforme mostrado no exemplo a seguir.

    
    using System;
    
    public class Example
    {
       public static void Main()
       {
          Double value1 = 4.565e153;
          Double value2 = 6.9375e172;
          Double result = value1 * value2;
          Console.WriteLine("PositiveInfinity: {0}", 
                             Double.IsPositiveInfinity(result));
          Console.WriteLine("NegativeInfinity: {0}\n", 
                            Double.IsNegativeInfinity(result));
    
          value1 = -value1;
          result = value1 * value2;
          Console.WriteLine("PositiveInfinity: {0}", 
                             Double.IsPositiveInfinity(result));
          Console.WriteLine("NegativeInfinity: {0}", 
                            Double.IsNegativeInfinity(result));
       }
    }                                                                 
    
    // The example displays the following output:
    //       PositiveInfinity: True
    //       NegativeInfinity: False
    //       
    //       PositiveInfinity: False
    //       NegativeInfinity: True
    
    
    

    PositiveInfinity também resulta de uma divisão por zero com um dividendo positivo, e os resultados de NegativeInfinity de uma divisão por zero com um dividendo negativo.

  • Se uma operação de ponto flutuante não é válido, o resultado da operação é NaN. Por exemplo, NaN resultados das seguintes operações:

  • Qualquer operação de ponto flutuante com uma entrada inválida. Por exemplo, chamando o método de Math.Sqrt com um valor negativo retorna NaN, como faz chamando o método de Math.Acos com um valor maior do que um ou menor que o menos um.

  • Qualquer operação com um argumento cujo valor é Double.NaN.

Funcionalidade de ponto flutuante

A estrutura de Double e os tipos relacionados fornece métodos para executar operações nas seguintes áreas:

  • Comparação de valores. Você pode chamar o método de Equals para determinar se dois valores de Double forem iguais, ou o método de CompareTo para determinar a relação entre dois valores.

    A estrutura de Double também oferece suporte a um conjunto completo de operadores de comparação. Por exemplo, você pode testar a igualdade ou desigualdade, ou a determinar se um valor é maior ou igual a outro. Se um dos operandos for um tipo numérico diferente Double, é convertido em Double antes de executar a comparação.

    Observação de cuidadoCuidado

    Devido às diferenças na precisão, dois valores de Double que você espera ser igual despejar podem ser diferentes, o que afeta o resultado da comparação. Consulte a seção de Testa a igualdade para obter mais informações sobre como comparar dois valores de Double .

    Você também pode chamar IsNaN, IsInfinity, IsPositiveInfinity, e os métodos de IsNegativeInfinity para testar esses valores especiais.

  • Operações matemáticas. Operações aritméticas comuns, como adição, subtração, multiplicação e divisão, são implementadas pelos compiladores e instruções de linguagem comum (CIL) de linguagem intermediária, e não por métodos de Double . Se um dos operandos em uma operação matemática é um tipo numérico diferente Double, é convertido em Double antes de executar a operação. O resultado da operação também um valor de Double .

    Outras operações matemáticas podem ser executadas chamando métodos de static (Shared no Visual Basic) na classe de System.Math . Inclui os métodos adicionais de uso geral para aritmética (como Math.Abs, Math.Sign, e Math.Sqrt), a geometria (como Math.Cos e Math.Sin), e o cálculo (como Math.Log).

    Você também pode manipular os bits individuais em um valor de Double . O método de BitConverter.DoubleToInt64Bits preserva o padrão de bit de um valor de Double em um inteiro de 64 bits. O método de BitConverter.GetBytes(Double) retorna o padrão de bits em uma matriz de bytes.

  • Arredondamento. Arredondamento é frequentemente usado como uma técnica para reduzir o impacto das diferenças entre os valores provocados por problemas de representação de ponto flutuante e a precisão. Você pode arredonda um valor de Double chamando o método de Math.Round .

  • Formatar. Você pode converter um valor de Double em sua representação de cadeia de caracteres chamando o método de ToString ou usando o recurso composto de formatação. Para obter informações sobre como as cadeias de formato controlam a representação de cadeia de caracteres de valores de ponto flutuante, consulte os tópicos de Cadeias de caracteres de formato numérico padrão e de Cadeias de caracteres de formato numérico personalizado .

  • Cadeias de caracteres de análise. Você pode converter representação de cadeia de caracteres de um valor de ponto flutuante a um valor de DoubleParse ou chamando o método de TryParse . Se a operação de análise falhar, o método de Parse gerou uma exceção, enquanto o método de TryParse retorna false.

  • Conversão de tipos. A estrutura de Double fornece uma implementação da interface explícita para a interface de IConvertible , que da suporte à conversão entre quaisquer dois tipos de dados padrão do.NET Framework. Os compiladores de idioma também dão suporte à conversão implícita de valores de todos tipos numéricos padrão restantes para os valores de Double . A conversão de um valor de qualquer tipo numérico padrão a Double é uma conversão da e não requer o usuário de um método de operador ou de conversão de conversão,

    Entretanto, a conversão de Int64 e os valores de Single podem envolver uma perda de precisão. A tabela a seguir lista as diferenças na precisão para cada um desses tipos:

    Tipo

    Precisão máxima

    Precisão interna

    Double

    15

    17

    Int64

    19 dígitos decimais

    19 dígitos decimais

    Single

    7 dígitos decimais

    9 dígitos decimais

    O problema de precisão afeta com mais frequência os valores de Single que são convertidos em valores de Double . No exemplo a seguir, dois valores gerados por operações idênticas de particionamento são diferentes porque um dos valores é um valor de ponto flutuante de precisão única convertido em Double.

    
    using System;
    
    public class Example
    {
       public static void Main()
       {
          Double value = .1;
          Double result1 = value * 10;
          Double result2 = 0;
          for (int ctr = 1; ctr <= 10; ctr++)
             result2 += value;
    
          Console.WriteLine(".1 * 10:           {0:R}", result1);
          Console.WriteLine(".1 Added 10 times: {0:R}", result2);
       }
    }
    // The example displays the following output:
    //       .1 * 10:           1
    //       .1 Added 10 times: 0.99999999999999989
    
    
    

O exemplo de código a seguir ilustra o uso de Double:


	// The Temperature class stores the temperature as a Double
	// and delegates most of the functionality to the Double
	// implementation.
	public class Temperature : IComparable, IFormattable 
    {
		// IComparable.CompareTo implementation.
		public int CompareTo(object obj) {
            if (obj == null) return 1;

			Temperature temp = obj as Temperature;
            if (obj != null) 
				return m_value.CompareTo(temp.m_value);
			else
     			throw new ArgumentException("object is not a Temperature");	
		}

		// IFormattable.ToString implementation.
		public string ToString(string format, IFormatProvider provider) {
			if( format != null ) {
				if( format.Equals("F") ) {
					return String.Format("{0}'F", this.Value.ToString());
				}
				if( format.Equals("C") ) {
					return String.Format("{0}'C", this.Celsius.ToString());
				}
			}

			return m_value.ToString(format, provider);
		}

		// Parses the temperature from a string in the form
		// [ws][sign]digits['F|'C][ws]
		public static Temperature Parse(string s, NumberStyles styles, IFormatProvider provider) {
			Temperature temp = new Temperature();

			if( s.TrimEnd(null).EndsWith("'F") ) {
				temp.Value = Double.Parse( s.Remove(s.LastIndexOf('\''), 2), styles, provider);
			}
			else if( s.TrimEnd(null).EndsWith("'C") ) {
				temp.Celsius = Double.Parse( s.Remove(s.LastIndexOf('\''), 2), styles, provider);
			}
			else {
				temp.Value = Double.Parse(s, styles, provider);
			}

			return temp;
		}

		// The value holder
		protected double m_value;

		public double Value {
			get {
				return m_value;
			}
			set {
				m_value = value;
			}
		}

		public double Celsius {
			get {
				return (m_value-32.0)/1.8;
			}
			set {
				m_value = 1.8*value+32.0;
			}
		}
	}


.NET Framework

Com suporte em: 4.5.2, 4.5.1, 4.5, 4, 3.5, 3.0, 2.0, 1.1, 1.0

.NET Framework Client Profile

Com suporte em: 4, 3.5 SP1

Biblioteca de Classes Portátil

Com suporte em: Biblioteca de Classes Portátil

.NET para aplicativos da Windows Store

Com suporte em: Windows 8

.NET para aplicativos do Windows Phone

Com suporte em: Windows Phone 8, Silverlight 8.1

Windows Phone 8.1, Windows Phone 8, Windows 8.1, Windows Server 2012 R2, Windows 8, Windows Server 2012, Windows 7, Windows Vista SP2, Windows Server 2008 (Função Server Core sem suporte), Windows Server 2008 R2 (Função Server Core com suporte com o SP1 ou posterior, Itanium sem suporte)

O .NET Framework não oferece suporte a todas as versões de cada plataforma. Para obter uma lista das versões com suporte, consulte Requisitos do sistema do .NET Framework.

Todos os membros desse tipo são segmento seguro. Os membros que aparecem para modificar o estado da instância, na verdade, retornam uma nova instância inicializada com o novo valor. Como com qualquer outro tipo, leitura e gravação a uma variável compartilhada que contém uma instância desse tipo deve ser protegida por um bloqueio para garantir segurança de segmentos.

Observação de cuidadoCuidado

A atribuição de uma instância desse tipo não é thread-safe em todas as plataformas de hardware porque a representação binária dessa instância pode ser muito grande para ser atribuída em uma única operação atômica.

Contribuições da comunidade

ADICIONAR
Mostrar:
© 2015 Microsoft