Double Estructura
TOC
Collapse the table of content
Expand the table of content
Este artículo se tradujo automáticamente. Para ver el artículo en inglés, active la casilla Inglés. Además, puede mostrar el texto en inglés en una ventana emergente si mueve el puntero del mouse sobre el texto.
Traducción
Inglés

Double (Estructura)

 

Representa un número de punto flotante de precisión doble.

Espacio de nombres:   System
Ensamblado:  mscorlib (en mscorlib.dll)

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

NombreDescripción
System_CAPS_pubmethodCompareTo(Double)

Compara esta instancia con un número de punto flotante de precisión doble especificado y devuelve un entero que indica si el valor de esta instancia es mayor, menor o igual que el valor del número de punto flotante de precisión doble especificado.

System_CAPS_pubmethodCompareTo(Object)

Compara esta instancia con un objeto especificado y devuelve un entero que indica si el valor de esta instancia es mayor, igual o menor que el valor del objeto especificado.

System_CAPS_pubmethodEquals(Double)

Devuelve un valor que indica si esta instancia y un objeto Double especificado representan el mismo valor.

System_CAPS_pubmethodEquals(Object)

Devuelve un valor que indica si esta instancia equivale a un objeto especificado.(Reemplaza a ValueType.Equals(Object)).

System_CAPS_pubmethodGetHashCode()

Devuelve el código hash de esta instancia.(Reemplaza a ValueType.GetHashCode()).

System_CAPS_pubmethodGetType()

Obtiene el Type de la instancia actual.(Heredado de Object.)

System_CAPS_pubmethodGetTypeCode()

Devuelve el TypeCode para el tipo de valor Double.

System_CAPS_pubmethodSystem_CAPS_staticIsInfinity(Double)

Devuelve un valor que indica si el número especificado se evalúa como infinito negativo o positivo.

System_CAPS_pubmethodSystem_CAPS_staticIsNaN(Double)

Devuelve un valor que indica si el valor especificado no es un número (NaN).

System_CAPS_pubmethodSystem_CAPS_staticIsNegativeInfinity(Double)

Devuelve un valor que indica si el número especificado se evalúa como infinito negativo.

System_CAPS_pubmethodSystem_CAPS_staticIsPositiveInfinity(Double)

Devuelve un valor que indica si el número especificado se evalúa como infinito positivo.

System_CAPS_pubmethodSystem_CAPS_staticParse(String)

Convierte la representación en forma de cadena de un número en el número de punto flotante de precisión doble equivalente.

System_CAPS_pubmethodSystem_CAPS_staticParse(String, IFormatProvider)

Convierte la representación en forma de cadena de un número con un formato específico de la referencia cultural especificado en el número de punto flotante de precisión doble equivalente.

System_CAPS_pubmethodSystem_CAPS_staticParse(String, NumberStyles)

Convierte la representación en forma de cadena de un número con un estilo especificado en el número de punto flotante de precisión doble equivalente.

System_CAPS_pubmethodSystem_CAPS_staticParse(String, NumberStyles, IFormatProvider)

Convierte la representación en forma de cadena de un número con un estilo y un formato específico de la referencia cultural especificados en el número de punto flotante de precisión doble equivalente.

System_CAPS_pubmethodToString()

Convierte el valor numérico de esta instancia en la representación de cadena equivalente.(Reemplaza a ValueType.ToString()).

System_CAPS_pubmethodToString(IFormatProvider)

Convierte el valor numérico de esta instancia en la representación de cadena equivalente usando la información de formato específica de la referencia cultural especificada.

System_CAPS_pubmethodToString(String)

Convierte el valor numérico de esta instancia en la representación de cadena equivalente usando el formato especificado.

System_CAPS_pubmethodToString(String, IFormatProvider)

Convierte el valor numérico de esta instancia en su representación de cadena equivalente mediante el formato y la información de formato específica de la referencia cultural que se especificaran.

System_CAPS_pubmethodSystem_CAPS_staticTryParse(String, Double)

Convierte la representación en forma de cadena de un número en el número de punto flotante de precisión doble equivalente. Un valor devuelto indica si la conversión se realizó correctamente o si se produjeron errores.

System_CAPS_pubmethodSystem_CAPS_staticTryParse(String, NumberStyles, IFormatProvider, Double)

Convierte la representación en forma de cadena de un número con un estilo y un formato específico de la referencia cultural especificados en el número de punto flotante de precisión doble equivalente. Un valor devuelto indica si la conversión se realizó correctamente o si se produjeron errores.

NombreDescripción
System_CAPS_pubfieldSystem_CAPS_staticEpsilon

Representa el menor valor Double positivo mayor que cero. Este campo es constante.

System_CAPS_pubfieldSystem_CAPS_staticMaxValue

Representa el mayor valor posible de un Double. Este campo es constante.

System_CAPS_pubfieldSystem_CAPS_staticMinValue

Representa el menor valor posible de un Double. Este campo es constante.

System_CAPS_pubfieldSystem_CAPS_staticNaN

Representa un valor no numérico (NaN). Este campo es constante.

System_CAPS_pubfieldSystem_CAPS_staticNegativeInfinity

Representa infinito negativo. Este campo es constante.

System_CAPS_pubfieldSystem_CAPS_staticPositiveInfinity

Representa infinito positivo. Este campo es constante.

NombreDescripción
System_CAPS_puboperatorSystem_CAPS_staticEquality(Double, Double)

Devuelve un valor que indica si dos valores Double especificados son iguales.

System_CAPS_puboperatorSystem_CAPS_staticGreaterThan(Double, Double)

Devuelve un valor que indica si un valor Double especificado es mayor que otro valor Double especificado.

System_CAPS_puboperatorSystem_CAPS_staticGreaterThanOrEqual(Double, Double)

Devuelve un valor que indica si un valor Double especificado es mayor o igual que otro valor Double especificado.

System_CAPS_puboperatorSystem_CAPS_staticInequality(Double, Double)

Devuelve un valor que indica si dos valores Double especificados no son iguales.

System_CAPS_puboperatorSystem_CAPS_staticLessThan(Double, Double)

Devuelve un valor que indica si un valor Double especificado es menor que otro valor Double especificado.

System_CAPS_puboperatorSystem_CAPS_staticLessThanOrEqual(Double, Double)

Devuelve un valor que indica si un valor Double especificado es menor o igual que otro valor Double especificado.

NombreDescripción
System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToBoolean(IFormatProvider)

Esta API admite la infraestructura de product y no está pensada para usarse directamente desde su código. Para una descripción de este miembro, vea IConvertible.ToBoolean.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToByte(IFormatProvider)

Esta API admite la infraestructura de product y no está pensada para usarse directamente desde su código. Para una descripción de este miembro, vea IConvertible.ToByte.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToChar(IFormatProvider)

Esta API admite la infraestructura de product y no está pensada para usarse directamente desde su código. No se admite esta conversión. Cualquier intento de usar este método produce una excepción InvalidCastException.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToDateTime(IFormatProvider)

Esta API admite la infraestructura de product y no está pensada para usarse directamente desde su código. No se admite esta conversión. Cualquier intento de usar este método produce una excepción InvalidCastException.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToDecimal(IFormatProvider)

Esta API admite la infraestructura de product y no está pensada para usarse directamente desde su código. Para una descripción de este miembro, vea IConvertible.ToDecimal.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToDouble(IFormatProvider)

Esta API admite la infraestructura de product y no está pensada para usarse directamente desde su código. Para una descripción de este miembro, vea IConvertible.ToDouble.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToInt16(IFormatProvider)

Esta API admite la infraestructura de product y no está pensada para usarse directamente desde su código. Para una descripción de este miembro, vea IConvertible.ToInt16.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToInt32(IFormatProvider)

Esta API admite la infraestructura de product y no está pensada para usarse directamente desde su código. Para una descripción de este miembro, vea IConvertible.ToInt32.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToInt64(IFormatProvider)

Esta API admite la infraestructura de product y no está pensada para usarse directamente desde su código. Para una descripción de este miembro, vea IConvertible.ToInt64.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToSByte(IFormatProvider)

Esta API admite la infraestructura de product y no está pensada para usarse directamente desde su código. Para una descripción de este miembro, vea IConvertible.ToSByte.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToSingle(IFormatProvider)

Esta API admite la infraestructura de product y no está pensada para usarse directamente desde su código. Para una descripción de este miembro, vea IConvertible.ToSingle.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToType(Type, IFormatProvider)

Esta API admite la infraestructura de product y no está pensada para usarse directamente desde su código. Para una descripción de este miembro, vea IConvertible.ToType.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToUInt16(IFormatProvider)

Esta API admite la infraestructura de product y no está pensada para usarse directamente desde su código. Para una descripción de este miembro, vea IConvertible.ToUInt16.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToUInt32(IFormatProvider)

Esta API admite la infraestructura de product y no está pensada para usarse directamente desde su código. Para una descripción de este miembro, vea IConvertible.ToUInt32.

System_CAPS_pubinterfaceSystem_CAPS_privmethodIConvertible.ToUInt64(IFormatProvider)

Esta API admite la infraestructura de product y no está pensada para usarse directamente desde su código. Para una descripción de este miembro, vea IConvertible.ToUInt64.

El Double tipo de valor representa un número de 64 bits de precisión doble con valores comprendidos entre negativo 1. 79769313486232e308 al positivo 1. 79769313486232e308, así como el cero positivo o negativo, PositiveInfinity, NegativeInfinity, y no un número (NaN). Está pensado para representar los valores que son muy pequeño o muy grande (por ejemplo, las distancias entre los planetas o galaxias) (masa molecular de una sustancia en kilogramos) y que a menudo son precisos (como la distancia desde la tierra a otro sistema solar), el Double tipo cumple la IEC 60559: 1989 (IEEE 754) estándar para aritmética binaria de punto flotante.

Este tema consta de las siguientes secciones:

El Double tipo de datos almacena valores de punto flotante de precisión doble en un formato binario de 64 bits, como se muestra en la tabla siguiente:

Parte

Bits

Exponentes o mantisa

0-51

Exponente

52-62

Inicio de sesión (0 = positivo, 1 = negativo)

63

Tal como fracciones decimales son no se puede representar con precisión los valores fraccionarios (por ejemplo, 1/3 o Math.PI), fracciones binarias son no puede representar algunos valores fraccionarios. Por ejemplo, 1/10, que se representa con precisión,.1 como una fracción decimal, se representa mediante.001100110011 como una fracción binaria con el patrón "0011" de repetición infinito. En este caso, el valor de punto flotante proporciona una representación imprecisa del número que representa. Realizar operaciones matemáticas adicionales en el valor de punto flotante original a menudo tiende a aumentar su falta de precisión. Por ejemplo, si se compara el resultado de multiplicar.1 por 10 y agregar.1 a.1 nueve veces, podemos ver esta adición, porque ha implicado ocho más operaciones, ha generado el resultado menos preciso. Tenga en cuenta que esta disparidad aparente sólo si se muestran las dos Double valores mediante la "R" cadena de formato numérico estándar, que si es necesario muestra todos los 17 dígitos de precisión admitida por el Double tipo.

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

Dado que algunos números no se puede representar exactamente como valores binarios fracciones, números de punto flotante pueden sólo números aproximados de real.

Todos los números de punto flotante también tienen un número limitado de dígitos significativos, que también determina la precisión con un valor de punto flotante se aproxima a un número real. Un Double valor tiene hasta 15 dígitos decimales de precisión, aunque internamente se mantiene un máximo de 17 dígitos. Esto significa que algunas operaciones de punto flotante pueden carecer de la precisión para cambiar un flotante valor de punto. Esto se muestra en el ejemplo siguiente. Define un valor de punto flotante muy grande y, a continuación, agrega el producto de Double.Epsilon y mil billones a él. El producto, sin embargo, es demasiado pequeño para modificar el valor de punto flotante original. Sus dígitos menos significativos es milésimas, mientras que el dígito más significativo en el producto es 1-312.

using System;

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

La precisión limitada de un número de punto flotante tiene varias consecuencias:

  • Dos números de punto flotante que parecen iguales para una precisión determinada podrían no son iguales porque sus dígitos menos significativos son diferentes. En el ejemplo siguiente, se suman una serie de números y el total se compara con el total esperado. Aunque los dos valores parecen ser el mismo, una llamada a la Equals método indica que no están.

    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).   
    

    Si cambia los elementos de formato en el Console.WriteLine(String, Object, Object) instrucción de {0} y {1} a {0:R} y {1:R} para mostrar todos los dígitos significativos de los dos Double valores, está claro que los dos valores no son iguales debido a una pérdida de precisión durante las operaciones de adición. En este caso, el problema puede resolverse mediante una llamada a la Math.Round(Double, Int32) método para redondear el Double valores a la precisión deseado antes de realizar la comparación.

  • Una operación matemática o de comparación que utiliza un número de punto flotante podría no producir el mismo resultado si se utiliza un número decimal, porque el número de punto flotante binario no podría ser igual al número decimal. Un ejemplo anterior muestra al mostrar el resultado de multiplicar.1 por 10 y agregar.1 veces.

    Cuando la precisión en las operaciones numéricas con valores fraccionarios es importante, puede usar el Decimal en lugar de Double tipo. Cuando la precisión en las operaciones numéricas con valores enteros más allá del intervalo de la Int64 o UInt64 tipos es importante, utilice la BigInteger tipo.

  • Un valor podría no ida y vuelta si está implicado un número de punto flotante. Un valor se dice que acudir si una operación convierte a un número de punto flotante original a otro formulario, una operación inversa transforma el formato convertido a un número de punto flotante y el último número de punto flotante no es igual al número de punto flotante original. Puede producir un error en el recorrido de ida y vuelta porque uno o más dígitos menos significativos se pierden o cambian durante una conversión. En el ejemplo siguiente, tres Double valores se convierten en cadenas y se guardan en un archivo. Como muestra el resultado, sin embargo, aunque los valores parecen ser idénticas, los valores restaurados no son iguales a los valores originales.

    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
    

    En este caso, los valores pueden ser la ida y vuelta correctamente mediante el uso de la "R" cadena de formato numérico estándar para conservar la precisión completa de Double valores, como se muestra en el ejemplo siguiente.

    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
    
  • Single valores tienen menor precisión que Double valores. Un Single valor que se convierte en un equivalente aparentemente Double a menudo no es igual a la Double valor debido a diferencias en la precisión. En el ejemplo siguiente, se asigna el resultado de operaciones de división idéntico a un Double y un Single valor. Después de la Single valor se convierte en un Double, se muestra una comparación de los dos valores que son iguales.

    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 este problema, utilice uno el Double en lugar de la Single tipo de datos o use el Round método para que ambos valores tienen la misma precisión.

Además, el resultado de las operaciones aritméticas y de asignación con Double valores pueden diferir ligeramente según la plataforma debido a la pérdida de precisión de la Double tipo. Por ejemplo, el resultado de asignar un literal Double valor puede diferir en las versiones de 32 bits y 64 bits de .NET Framework. En el ejemplo siguiente se muestra esta diferencia cuando el literal value - 4.42330604244772E-305 y una variable cuyo valor es - 4.42330604244772E-305 se asignan a un Double variable. Tenga en cuenta que el resultado de la Parse(String) método en este caso no sufren una pérdida de precisión.

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      

Para considerarse iguales, dos Double valores deben representar valores idénticos. Sin embargo, debido a diferencias en precisión entre valores, o debido a una pérdida de precisión por uno o ambos valores, valores de punto flotante que se esperan que sean idénticos a menudo resultan para ser desigual debido a diferencias en sus dígitos menos significativos. Como resultado, las llamadas a la Equals método para determinar si dos valores son iguales, o llamadas a la CompareTo método para determinar la relación entre dos Double valores, a menudo producen resultados inesperados. Esto es evidente en el ejemplo siguiente, donde dos igual aparentemente Double valores resultan para ser desigual porque la primera tiene 15 dígitos de precisión, mientras que el segundo tiene 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

Los valores calculados que siguen diferentes rutas de código y que se manipulan de maneras diferentes a menudo resultar desiguales. En el ejemplo siguiente, un Double se eleva al cuadrado el valor y, a continuación, se calcula la raíz cuadrada para restaurar el valor original. Un segundo Double se multiplica por 3.51 y cuadrado antes de la raíz cuadrada del resultado se divide por 3.51 para restaurar el valor original. Aunque los dos valores parecen ser idénticas, una llamada a la Equals(Double) método indica que no son iguales. La cadena de formato estándar "R" para devolver una cadena de resultado que muestra todos los dígitos significativos de cada valor de tipo Double, muestra que el segundo valor es.0000000000001 menor que el primero.

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

En casos donde es probable que afecta al resultado de una comparación de una pérdida de precisión, puede adoptar cualquiera de las siguientes alternativas para llamar a la Equals o CompareTo método:

  • Llame a la Math.Round método para asegurarse de que ambos valores tienen la misma precisión. En el ejemplo siguiente se modifica un ejemplo anterior para utilizar este enfoque para que dos valores fraccionarios son 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
    

    Sin embargo, tenga en cuenta que el problema de precisión sigue siendo aplicable al redondeo de valores de punto medio. Para obtener más información, vea el método Math.Round(Double, Int32, MidpointRounding).

  • Probar la igualdad aproximada en lugar de igualdad. Esto requiere que se defina en absoluto cantidad por la que los dos valores pueden diferir pero todavía sea igual o definir una cantidad relativa por el que el valor más pequeño puede diferir del valor mayor.

    System_CAPS_warningAdvertencia

    Double.Epsilon a veces se utiliza como una medida de la distancia entre dos absoluta Double al probar la igualdad de los valores. Sin embargo, Double.Epsilon mide el menor valor posible que se puede sumar o restar, un Double cuyo valor es cero. Para la mayoría de valores positivos y negativos Double valores, el valor de Double.Epsilon es demasiado pequeño para que lo detecte. Por lo tanto, salvo los valores que son iguales a cero, no se recomienda su uso en las pruebas de igualdad.

    En el ejemplo siguiente se utiliza el último enfoque para definir una IsApproximatelyEqual método que comprueba la diferencia relativa entre dos valores. También se compara el resultado de las llamadas a la IsApproximatelyEqual (método) y Equals(Double) (método).

    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
    

A diferencia de las operaciones con tipos integrales, que inician excepciones en caso de desbordamiento o de operaciones ilegales, como la división por cero, las operaciones con valores de punto flotante no producen excepciones. En su lugar, en situaciones excepcionales, el resultado de una operación de punto flotante es cero, infinito positivo, infinito negativo o no es un número (NaN):

  • Si el resultado de una operación de punto flotante es demasiado pequeño para el formato de destino, el resultado es cero. Esto puede ocurrir cuando se multiplican dos números muy pequeños, como se muestra en el ejemplo siguiente.

    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
    
  • Si la magnitud del resultado de una operación de punto flotante supera el intervalo del formato de destino, el resultado de la operación es PositiveInfinity o NegativeInfinity, según corresponda para el signo del resultado. El resultado de una operación que se desborda Double.MaxValue es PositiveInfinity, y el resultado de una operación que se desborda Double.MinValue es NegativeInfinity, como se muestra en el ejemplo siguiente.

    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 También se produce de una división por cero con dividendo positivo, y NegativeInfinity como resultado de una división por cero con dividendo negativo.

  • Si una operación de punto flotante no es válida, el resultado de la operación es NaN. Por ejemplo, NaN resultante de las operaciones siguientes:

  • Cualquier operación de punto flotante con una entrada no válida. Por ejemplo, al llamar a la Math.Sqrt devuelve el método con un valor negativo NaN, al igual que llamar a la Math.Acos método con un valor mayor que 1 o menor que uno negativo.

  • Cualquier operación con un argumento cuyo valor es Double.NaN.

El Double estructura no define ningún operador de conversión explícito o implícito; en su lugar, el compilador implementa las conversiones.

La conversión del valor de cualquier tipo numérico primitivo a un Double es una conversión de ampliación y, por tanto, no requiere un operador de conversión explícita ni llamar a un método de conversión a menos que un compilador requiere explícitamente. Por ejemplo, el compilador de C# requiere un operador de conversión para las conversiones de Decimal a Double, mientras que el compilador de Visual Basic no. En el ejemplo siguiente se convierte el valor máximo o mínimo de los otros tipos numéricos primitivos a una Double.

using System;

public class Example
{
   public static void Main()
   {
      dynamic[] values = { Byte.MinValue, Byte.MaxValue, Decimal.MinValue,
                           Decimal.MaxValue, Int16.MinValue, Int16.MaxValue,
                           Int32.MinValue, Int32.MaxValue, Int64.MinValue,
                           Int64.MaxValue, SByte.MinValue, SByte.MaxValue,
                           Single.MinValue, Single.MaxValue, UInt16.MinValue,
                           UInt16.MaxValue, UInt32.MinValue, UInt32.MaxValue,
                           UInt64.MinValue, UInt64.MaxValue };
      double dblValue;
      foreach (var value in values) {
         if (value.GetType() == typeof(Decimal))
            dblValue = (Double) value;
         else
            dblValue = value;
         Console.WriteLine("{0} ({1}) --> {2:R} ({3})",
                           value, value.GetType().Name,
                           dblValue, dblValue.GetType().Name);
      }
   }
}
// The example displays the following output:
//    0 (Byte) --> 0 (Double)
//    255 (Byte) --> 255 (Double)
//    -79228162514264337593543950335 (Decimal) --> -7.9228162514264338E+28 (Double)
//    79228162514264337593543950335 (Decimal) --> 7.9228162514264338E+28 (Double)
//    -32768 (Int16) --> -32768 (Double)
//    32767 (Int16) --> 32767 (Double)
//    -2147483648 (Int32) --> -2147483648 (Double)
//    2147483647 (Int32) --> 2147483647 (Double)
//    -9223372036854775808 (Int64) --> -9.2233720368547758E+18 (Double)
//    9223372036854775807 (Int64) --> 9.2233720368547758E+18 (Double)
//    -128 (SByte) --> -128 (Double)
//    127 (SByte) --> 127 (Double)
//    -3.402823E+38 (Single) --> -3.4028234663852886E+38 (Double)
//    3.402823E+38 (Single) --> 3.4028234663852886E+38 (Double)
//    0 (UInt16) --> 0 (Double)
//    65535 (UInt16) --> 65535 (Double)
//    0 (UInt32) --> 0 (Double)
//    4294967295 (UInt32) --> 4294967295 (Double)
//    0 (UInt64) --> 0 (Double)
//    18446744073709551615 (UInt64) --> 1.8446744073709552E+19 (Double)

Además, el Single valores Single.NaN, Single.PositiveInfinity, y Single.NegativeInfinity convertir a Double.NaN, Double.PositiveInfinity, y Double.NegativeInfinity, respectivamente.

Tenga en cuenta que la conversión del valor de algunos tipos numéricos a un Double valor puede conllevar una pérdida de precisión. Como se muestra en el ejemplo, una pérdida de precisión es posible al convertir Decimal, Int64, Single, y UInt64 valores Double valores.

La conversión de un Double valor a un valor de cualquier otro tipo de datos numérico primitivo es una conversión de restricción y requiere un operador de conversión (en C#), un método de conversión (en Visual Basic) o una llamada a un Convert (método). Valores que están fuera del intervalo del tipo de datos de destino, que están definidos por el tipo de destino MinValue y MaxValue se comportan de propiedades, como se muestra en la tabla siguiente.

Tipo de destino

Resultado

Cualquier tipo entero

Un OverflowException excepción si la conversión se realiza en un contexto comprobado.

Si la conversión se produce en un contexto no comprobado (el valor predeterminado en C#), la operación de conversión se realiza correctamente pero se desborda el valor.

Decimal

Un OverflowException excepción.

Single

Single.NegativeInfinity para los valores negativos.

Single.PositiveInfinity para los valores positivos.

Además, Double.NaN, Double.PositiveInfinity, y Double.NegativeInfinity producir una OverflowException para las conversiones de enteros en un contexto comprobado, pero estos desbordamiento valores cuando se convierten en enteros en un contexto no comprobado. Para las conversiones a Decimal, siempre producen un OverflowException. Para las conversiones a Single, se convierten a Single.NaN, Single.PositiveInfinity, y Single.NegativeInfinity, respectivamente.

Tenga en cuenta que puede producir una pérdida de precisión en la conversión de un Double valor a otro tipo numérico. En el caso de conversión no integrales Double valores, como se muestra en el resultado del ejemplo, el componente fraccionario se pierde cuando el Double valor se redondea (como en Visual Basic) o se truncan (como en C#). Para las conversiones a Decimal y Single valores, la Double valor no puede tener una representación precisa en el tipo de datos de destino.

En el ejemplo siguiente se convierte un número de Double valores de otros tipos numéricos. Las conversiones se producen en un contexto comprobado en Visual Basic (predeterminado) y en C# (porque el comprueban palabra clave). El resultado del ejemplo muestra el resultado para las conversiones en ambos un comprobado un contexto no comprobado. Puede realizar conversiones en un contexto no comprobado en Visual Basic al compilar con la /removeintchecks+ conmutador de compilador y en C# como comentario el checked instrucción.

using System;

public class Example
{
   public static void Main()
   {
      Double[] values = { Double.MinValue, -67890.1234, -12345.6789,
                          12345.6789, 67890.1234, Double.MaxValue,
                          Double.NaN, Double.PositiveInfinity,
                          Double.NegativeInfinity };
      checked {
         foreach (var value in values) {
            try {
                Int64 lValue = (long) value;
                Console.WriteLine("{0} ({1}) --> {2} (0x{2:X16}) ({3})",
                                  value, value.GetType().Name,
                                  lValue, lValue.GetType().Name);
            }
            catch (OverflowException) {
               Console.WriteLine("Unable to convert {0} to Int64.", value);
            }
            try {
                UInt64 ulValue = (ulong) value;
                Console.WriteLine("{0} ({1}) --> {2} (0x{2:X16}) ({3})",
                                  value, value.GetType().Name,
                                  ulValue, ulValue.GetType().Name);
            }
            catch (OverflowException) {
               Console.WriteLine("Unable to convert {0} to UInt64.", value);
            }
            try {
                Decimal dValue = (decimal) value;
                Console.WriteLine("{0} ({1}) --> {2} ({3})",
                                  value, value.GetType().Name,
                                  dValue, dValue.GetType().Name);
            }
            catch (OverflowException) {
               Console.WriteLine("Unable to convert {0} to Decimal.", value);
            }
            try {
                Single sValue = (float) value;
                Console.WriteLine("{0} ({1}) --> {2} ({3})",
                                  value, value.GetType().Name,
                                  sValue, sValue.GetType().Name);
            }
            catch (OverflowException) {
               Console.WriteLine("Unable to convert {0} to Single.", value);
            }
            Console.WriteLine();
         }
      }
   }
}
// The example displays the following output for conversions performed
// in a checked context:
//       Unable to convert -1.79769313486232E+308 to Int64.
//       Unable to convert -1.79769313486232E+308 to UInt64.
//       Unable to convert -1.79769313486232E+308 to Decimal.
//       -1.79769313486232E+308 (Double) --> -Infinity (Single)
//
//       -67890.1234 (Double) --> -67890 (0xFFFFFFFFFFFEF6CE) (Int64)
//       Unable to convert -67890.1234 to UInt64.
//       -67890.1234 (Double) --> -67890.1234 (Decimal)
//       -67890.1234 (Double) --> -67890.13 (Single)
//
//       -12345.6789 (Double) --> -12345 (0xFFFFFFFFFFFFCFC7) (Int64)
//       Unable to convert -12345.6789 to UInt64.
//       -12345.6789 (Double) --> -12345.6789 (Decimal)
//       -12345.6789 (Double) --> -12345.68 (Single)
//
//       12345.6789 (Double) --> 12345 (0x0000000000003039) (Int64)
//       12345.6789 (Double) --> 12345 (0x0000000000003039) (UInt64)
//       12345.6789 (Double) --> 12345.6789 (Decimal)
//       12345.6789 (Double) --> 12345.68 (Single)
//
//       67890.1234 (Double) --> 67890 (0x0000000000010932) (Int64)
//       67890.1234 (Double) --> 67890 (0x0000000000010932) (UInt64)
//       67890.1234 (Double) --> 67890.1234 (Decimal)
//       67890.1234 (Double) --> 67890.13 (Single)
//
//       Unable to convert 1.79769313486232E+308 to Int64.
//       Unable to convert 1.79769313486232E+308 to UInt64.
//       Unable to convert 1.79769313486232E+308 to Decimal.
//       1.79769313486232E+308 (Double) --> Infinity (Single)
//
//       Unable to convert NaN to Int64.
//       Unable to convert NaN to UInt64.
//       Unable to convert NaN to Decimal.
//       NaN (Double) --> NaN (Single)
//
//       Unable to convert Infinity to Int64.
//       Unable to convert Infinity to UInt64.
//       Unable to convert Infinity to Decimal.
//       Infinity (Double) --> Infinity (Single)
//
//       Unable to convert -Infinity to Int64.
//       Unable to convert -Infinity to UInt64.
//       Unable to convert -Infinity to Decimal.
//       -Infinity (Double) --> -Infinity (Single)
// The example displays the following output for conversions performed
// in an unchecked context:
//       -1.79769313486232E+308 (Double) --> -9223372036854775808 (0x8000000000000000) (Int64)
//       -1.79769313486232E+308 (Double) --> 9223372036854775808 (0x8000000000000000) (UInt64)
//       Unable to convert -1.79769313486232E+308 to Decimal.
//       -1.79769313486232E+308 (Double) --> -Infinity (Single)
//
//       -67890.1234 (Double) --> -67890 (0xFFFFFFFFFFFEF6CE) (Int64)
//       -67890.1234 (Double) --> 18446744073709483726 (0xFFFFFFFFFFFEF6CE) (UInt64)
//       -67890.1234 (Double) --> -67890.1234 (Decimal)
//       -67890.1234 (Double) --> -67890.13 (Single)
//
//       -12345.6789 (Double) --> -12345 (0xFFFFFFFFFFFFCFC7) (Int64)
//       -12345.6789 (Double) --> 18446744073709539271 (0xFFFFFFFFFFFFCFC7) (UInt64)
//       -12345.6789 (Double) --> -12345.6789 (Decimal)
//       -12345.6789 (Double) --> -12345.68 (Single)
//
//       12345.6789 (Double) --> 12345 (0x0000000000003039) (Int64)
//       12345.6789 (Double) --> 12345 (0x0000000000003039) (UInt64)
//       12345.6789 (Double) --> 12345.6789 (Decimal)
//       12345.6789 (Double) --> 12345.68 (Single)
//
//       67890.1234 (Double) --> 67890 (0x0000000000010932) (Int64)
//       67890.1234 (Double) --> 67890 (0x0000000000010932) (UInt64)
//       67890.1234 (Double) --> 67890.1234 (Decimal)
//       67890.1234 (Double) --> 67890.13 (Single)
//
//       1.79769313486232E+308 (Double) --> -9223372036854775808 (0x8000000000000000) (Int64)
//       1.79769313486232E+308 (Double) --> 0 (0x0000000000000000) (UInt64)
//       Unable to convert 1.79769313486232E+308 to Decimal.
//       1.79769313486232E+308 (Double) --> Infinity (Single)
//
//       NaN (Double) --> -9223372036854775808 (0x8000000000000000) (Int64)
//       NaN (Double) --> 0 (0x0000000000000000) (UInt64)
//       Unable to convert NaN to Decimal.
//       NaN (Double) --> NaN (Single)
//
//       Infinity (Double) --> -9223372036854775808 (0x8000000000000000) (Int64)
//       Infinity (Double) --> 0 (0x0000000000000000) (UInt64)
//       Unable to convert Infinity to Decimal.
//       Infinity (Double) --> Infinity (Single)
//
//       -Infinity (Double) --> -9223372036854775808 (0x8000000000000000) (Int64)
//       -Infinity (Double) --> 9223372036854775808 (0x8000000000000000) (UInt64)
//       Unable to convert -Infinity to Decimal.
//       -Infinity (Double) --> -Infinity (Single)

Para obtener más información acerca de la conversión de tipos numéricos, vea Conversión de tipos en .NET Framework y Tablas de conversión de tipos en .NET Framework.

El Double estructura y los tipos relacionados proporcionan métodos para realizar operaciones en las siguientes áreas:

  • Comparación de valores. Puede llamar a la Equals método para determinar si dos Double valores son iguales, o la CompareTo método para determinar la relación entre dos valores.

    El Double estructura también admite un conjunto completo de operadores de comparación. Por ejemplo, puede comprobar la igualdad o desigualdad o determinar si un valor es mayor o igual a otro. Si uno de los operandos es un tipo numérico distinto de un Double, se convierte en un Double antes de realizar la comparación.

    System_CAPS_warningAdvertencia

    Debido a las diferencias en precisión, dos Double valores que se esperan que sea igual que resultó para ser desigual, que afecta al resultado de la comparación. Consulte la comprobación de igualdad sección para obtener más información acerca de cómo comparar dos Double valores.

    También puede llamar a la IsNaN, IsInfinity, IsPositiveInfinity, y IsNegativeInfinity métodos para comprobar estos valores especiales.

  • Operaciones matemáticas. Operaciones aritméticas comunes, como suma, resta, multiplicación y división, se implementan mediante compiladores de lenguaje y las instrucciones de Common Intermediate Language (CIL), en lugar de Double métodos. Si uno de los operandos de una operación matemática es un tipo numérico distinto de un Double, se convierte en un Double antes de realizar la operación. El resultado de la operación es también un Double valor.

    Otras operaciones matemáticas pueden realizarse mediante una llamada a static (Shared en Visual Basic) métodos en la System.Math clase. Incluye métodos adicionales que se utiliza normalmente para las operaciones aritméticas (como Math.Abs, Math.Sign, y Math.Sqrt), geometría (como Math.Cos y Math.Sin) y el cálculo (como Math.Log).

    También puede manipular los bits individuales en un Double valor. El BitConverter.DoubleToInt64Bits método conserva un Double valor de patrón de bits en un entero de 64 bits. El BitConverter.GetBytes(Double) método devuelve su patrón de bits en una matriz de bytes.

  • Redondeo. Redondeo a menudo se utiliza como una técnica para reducir el impacto de las diferencias entre los valores que se deben a problemas de representación de punto flotante y precisión. Se puede redondear un Double valor llamando el Math.Round método.

  • Formato. Puede convertir un Double valor en su representación de cadena mediante una llamada a la ToString método o mediante la característica de formato compuesto. Para obtener información sobre la forma en que las cadenas de formato controlan la representación de cadena de valores de punto flotante, consulte el Cadenas con formato numérico estándar y Cadenas con formato numérico personalizado temas.

  • Analizar cadenas. Puede convertir la representación de cadena de un valor de punto flotante a un Double valor llamando el Parse o TryParse (método). Si se produce un error en la operación de análisis, el Parse método produce una excepción, mientras que el TryParse método devuelve false.

  • La conversión de tipos. El Double estructura proporciona una implementación de interfaz explícita para la IConvertible interfaz, que admite la conversión entre los dos tipos de datos estándares de .NET Framework. Los compiladores de lenguajes también admiten la conversión implícita de valores de todos los demás tipos numéricos estándares para Double valores. Conversión de un valor de cualquier tipo numérico estándar para una Double es una conversión de ampliación y no requiere que el usuario de un método de conversión de operador o conversión,

    Sin embargo, la conversión de Int64 y Single valores pueden conllevar una pérdida de precisión. En la tabla siguiente se enumera las diferencias en la precisión para cada uno de estos tipos:

    Tipo

    Precisión máxima

    Precisión interna

    Double

    15

    17

    Int64

    19 dígitos decimales

    19 dígitos decimales

    Single

    7 dígitos decimales

    9 dígitos decimales

    El problema de precisión con más frecuencia afecta Single valores que se convierten en Double valores. En el ejemplo siguiente, dos valores generados por operaciones de división idénticos no son iguales porque uno de los valores de un valor convertido a de punto flotante de precisión sencilla un 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
    

En el ejemplo de código siguiente se muestra el 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;
		}
	}
}

Universal Windows Platform
Disponible desde 8
.NET Framework
Disponible desde 1.1
Portable Class Library
Compatible con: portable .NET platforms
Silverlight
Disponible desde 2.0
Windows Phone Silverlight
Disponible desde 7.0
Windows Phone
Disponible desde 8.1

Todos los miembros de este tipo son seguros para subprocesos. Los miembros que aparecen modificar el estado de instancia realmente devuelven una nueva instancia inicializada con el nuevo valor. Como con cualquier otro tipo, leer y escribir en una variable compartida que contiene una instancia de este tipo deben estar protegidos por un bloqueo para garantizar la seguridad para subprocesos.

System_CAPS_cautionPrecaución

Asigne una instancia de este tipo no es segura para subprocesos en todas las plataformas de hardware, porque la representación binaria de la instancia puede ser demasiado grande para la asignación en una única operación atómica.

Volver al principio
Mostrar:
© 2016 Microsoft