Single Estructura

Definición

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

public value class float : IComparable, IComparable<float>, IConvertible, IEquatable<float>, IFormattable
public value class float : IComparable, IComparable<float>, IConvertible, IEquatable<float>, ISpanFormattable
public value class float : IAdditionOperators<float, float, float>, IAdditiveIdentity<float, float>, IBinaryFloatingPoint<float>, IBinaryNumber<float>, IBitwiseOperators<float, float, float>, IComparable<float>, IComparisonOperators<float, float>, IConvertible, IDecrementOperators<float>, IDivisionOperators<float, float, float>, IEqualityOperators<float, float>, IEquatable<float>, IFloatingPoint<float>, IIncrementOperators<float>, IMinMaxValue<float>, IModulusOperators<float, float, float>, IMultiplicativeIdentity<float, float>, IMultiplyOperators<float, float, float>, INumber<float>, IParseable<float>, ISignedNumber<float>, ISpanParseable<float>, ISubtractionOperators<float, float, float>, IUnaryNegationOperators<float, float>, IUnaryPlusOperators<float, float>
public value class float : IComparable, IConvertible, IFormattable
public value class float : IComparable, IComparable<float>, IEquatable<float>, IFormattable
public struct Single : IComparable, IComparable<float>, IConvertible, IEquatable<float>, IFormattable
public readonly struct Single : IComparable, IComparable<float>, IConvertible, IEquatable<float>, IFormattable
public readonly struct Single : IComparable, IComparable<float>, IConvertible, IEquatable<float>, ISpanFormattable
public readonly struct Single : IAdditionOperators<float,float,float>, IAdditiveIdentity<float,float>, IBinaryFloatingPoint<float>, IBinaryNumber<float>, IBitwiseOperators<float,float,float>, IComparable<float>, IComparisonOperators<float,float>, IConvertible, IDecrementOperators<float>, IDivisionOperators<float,float,float>, IEqualityOperators<float,float>, IEquatable<float>, IFloatingPoint<float>, IIncrementOperators<float>, IMinMaxValue<float>, IModulusOperators<float,float,float>, IMultiplicativeIdentity<float,float>, IMultiplyOperators<float,float,float>, INumber<float>, IParseable<float>, ISignedNumber<float>, ISpanParseable<float>, ISubtractionOperators<float,float,float>, IUnaryNegationOperators<float,float>, IUnaryPlusOperators<float,float>
[System.Serializable]
public struct Single : IComparable, IConvertible, IFormattable
[System.Serializable]
[System.Runtime.InteropServices.ComVisible(true)]
public struct Single : IComparable, IComparable<float>, IConvertible, IEquatable<float>, IFormattable
public struct Single : IComparable, IComparable<float>, IEquatable<float>, IFormattable
type single = struct
    interface IConvertible
    interface IFormattable
type single = struct
    interface IConvertible
    interface ISpanFormattable
    interface IFormattable
type single = struct
    interface IConvertible
    interface ISpanFormattable
    interface IFormattable
    interface IBinaryFloatingPoint<single>
    interface IBinaryNumber<single>
    interface IBitwiseOperators<single, single, single>
    interface INumber<single>
    interface IAdditionOperators<single, single, single>
    interface IAdditiveIdentity<single, single>
    interface IComparisonOperators<single, single>
    interface IEqualityOperators<single, single>
    interface IDecrementOperators<single>
    interface IDivisionOperators<single, single, single>
    interface IIncrementOperators<single>
    interface IModulusOperators<single, single, single>
    interface IMultiplicativeIdentity<single, single>
    interface IMultiplyOperators<single, single, single>
    interface IParseable<single>
    interface ISpanParseable<single>
    interface ISubtractionOperators<single, single, single>
    interface IUnaryNegationOperators<single, single>
    interface IUnaryPlusOperators<single, single>
    interface IFloatingPoint<single>
    interface ISignedNumber<single>
    interface IMinMaxValue<single>
[<System.Serializable>]
type single = struct
    interface IFormattable
    interface IConvertible
[<System.Serializable>]
[<System.Runtime.InteropServices.ComVisible(true)>]
type single = struct
    interface IFormattable
    interface IConvertible
type single = struct
    interface IFormattable
Public Structure Single
Implements IComparable, IComparable(Of Single), IConvertible, IEquatable(Of Single), IFormattable
Public Structure Single
Implements IComparable, IComparable(Of Single), IConvertible, IEquatable(Of Single), ISpanFormattable
Public Structure Single
Implements IAdditionOperators(Of Single, Single, Single), IAdditiveIdentity(Of Single, Single), IBinaryFloatingPoint(Of Single), IBinaryNumber(Of Single), IBitwiseOperators(Of Single, Single, Single), IComparable(Of Single), IComparisonOperators(Of Single, Single), IConvertible, IDecrementOperators(Of Single), IDivisionOperators(Of Single, Single, Single), IEqualityOperators(Of Single, Single), IEquatable(Of Single), IFloatingPoint(Of Single), IIncrementOperators(Of Single), IMinMaxValue(Of Single), IModulusOperators(Of Single, Single, Single), IMultiplicativeIdentity(Of Single, Single), IMultiplyOperators(Of Single, Single, Single), INumber(Of Single), IParseable(Of Single), ISignedNumber(Of Single), ISpanParseable(Of Single), ISubtractionOperators(Of Single, Single, Single), IUnaryNegationOperators(Of Single, Single), IUnaryPlusOperators(Of Single, Single)
Public Structure Single
Implements IComparable, IConvertible, IFormattable
Public Structure Single
Implements IComparable, IComparable(Of Single), IEquatable(Of Single), IFormattable
Herencia
Single
Atributos
Implementaciones
IComparable IComparable<Single> IConvertible IEquatable<Single> IFormattable ISpanFormattable IAdditionOperators<Single,Single,Single> IAdditionOperators<TSelf,TSelf,TSelf> IAdditiveIdentity<Single,Single> IAdditiveIdentity<TSelf,TSelf> IBinaryFloatingPoint<Single> IBinaryNumber<Single> IBinaryNumber<TSelf> IBitwiseOperators<Single,Single,Single> IBitwiseOperators<TSelf,TSelf,TSelf> IComparable<TOther> IComparable<TSelf> IComparisonOperators<Single,Single> IComparisonOperators<TSelf,TSelf> IDecrementOperators<Single> IDecrementOperators<TSelf> IDivisionOperators<Single,Single,Single> IDivisionOperators<TSelf,TSelf,TSelf> IEqualityOperators<Single,Single> IEqualityOperators<TSelf,TOther> IEqualityOperators<TSelf,TSelf> IEquatable<TOther> IEquatable<TSelf> IFloatingPoint<Single> IFloatingPoint<TSelf> IIncrementOperators<Single> IIncrementOperators<TSelf> IMinMaxValue<Single> IModulusOperators<Single,Single,Single> IModulusOperators<TSelf,TSelf,TSelf> IMultiplicativeIdentity<Single,Single> IMultiplicativeIdentity<TSelf,TSelf> IMultiplyOperators<Single,Single,Single> IMultiplyOperators<TSelf,TSelf,TSelf> INumber<Single> INumber<TSelf> IParseable<Single> IParseable<TSelf> ISignedNumber<Single> ISignedNumber<TSelf> ISpanParseable<Single> ISpanParseable<TSelf> ISubtractionOperators<Single,Single,Single> ISubtractionOperators<TSelf,TSelf,TSelf> IUnaryNegationOperators<Single,Single> IUnaryNegationOperators<TSelf,TSelf> IUnaryPlusOperators<Single,Single> IUnaryPlusOperators<TSelf,TSelf>

Comentarios

El Single tipo de valor representa un número de 32 bits de precisión sencilla con valores que van desde 3,402823e38 negativo hasta 3,402823e38, así como cero positivo o negativo, PositiveInfinity, NegativeInfinityy no un número (NaN). Está diseñado para representar valores extremadamente grandes (como distancias entre planetas o galaxias) o extremadamente pequeños (como la masa molecular de una sustancia en kilogramos) y que a menudo son imprecisos (como la distancia de la tierra a otro sistema solar). El Single tipo cumple con el estándar IEC 60559:1989 (IEEE 754) para la aritmética de punto flotante binario.

Este artículo consta de las secciones siguientes:

System.Single proporciona métodos para comparar instancias de este tipo, convertir el valor de una instancia en su representación de cadena y convertir la representación de cadena de un número en una instancia de este tipo. Para obtener información sobre cómo los códigos de especificación de formato controlan la representación de cadena de los tipos de valor, vea Tipos de formato, Cadenas de formato numérico estándar y Cadenas de formato numérico personalizado.

Representación y precisión de punto flotante

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

Parte Bits
Significand o mantisa 0-22
Exponente 23-30
Signo (0 = positivo, 1 = negativo) 31

Al igual que las fracciones decimales no pueden representar con precisión algunos valores fraccionarios (como 1/3 o Math.PI), las fracciones binarias no pueden representar algunos valores fraccionarios. Por ejemplo, 2/10, representado precisamente por .2 como una fracción decimal, se representa mediante .0011111001001100 como una fracción binaria, con el patrón "1100" que se repite en infinito. En este caso, el valor de punto flotante proporciona una representación imprecisa del número que representa. La realización de operaciones matemáticas adicionales en el valor de punto flotante original a menudo aumenta su falta de precisión. Por ejemplo, si compara los resultados de multiplicar .3 por 10 y agregar .3 a .3 nueve veces, verá que la adición produce el resultado menos preciso, ya que implica ocho operaciones más que multiplicación. Tenga en cuenta que esta disparidad solo es evidente si se muestran los dos Single valores mediante la cadena de formato numérico estándar "R", que, si es necesario, muestra todos los 9 dígitos de precisión admitidos por el Single tipo.

using System;

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

      Console.WriteLine(".2 * 10:           {0:R}", result1);
      Console.WriteLine(".2 Added 10 times: {0:R}", result2);
   }
}
// The example displays the following output:
//       .2 * 10:           2
//       .2 Added 10 times: 2.00000024
let value = 0.2f
let result1 = value * 10f
let mutable result2 = 0f
for _ = 1 to 10 do
    result2 <- result2 + value

printfn $".2 * 10:           {result1:R}"
printfn $".2 Added 10 times: {result2:R}"
// The example displays the following output:
//       .2 * 10:           2
//       .2 Added 10 times: 2.00000024
Module Example
   Public Sub Main()
      Dim value As Single = .2
      Dim result1 As Single = value * 10
      Dim result2 As Single
      For ctr As Integer = 1 To 10
         result2 += value
      Next
      Console.WriteLine(".2 * 10:           {0:R}", result1)
      Console.WriteLine(".2 Added 10 times: {0:R}", result2)
   End Sub
End Module
' The example displays the following output:
'       .2 * 10:           2
'       .2 Added 10 times: 2.00000024

Dado que algunos números no se pueden representar exactamente como valores binarios fraccionarios, los números de punto flotante solo pueden aproximarse a números reales.

Todos los números de punto flotante tienen un número limitado de dígitos significativos, que también determina con qué precisión un valor de punto flotante se aproxima a un número real. Un Single valor tiene hasta 7 dígitos decimales de precisión, aunque se mantiene internamente un máximo de 9 dígitos. Esto significa que algunas operaciones de punto flotante pueden carecer de precisión para cambiar un valor de punto flotante. En el ejemplo siguiente se define un valor de punto flotante de precisión sencilla grande y, a continuación, se agrega el producto de Single.Epsilon y un cuadrilátero. Sin embargo, el producto es demasiado pequeño para modificar el valor de punto flotante original. Su dígito menos significativo es milésimas, mientras que el dígito más significativo del producto es de 10 a 30.

using System;

public class Example
{
   public static void Main()
   {
      Single value = 123.456f;
      Single additional = Single.Epsilon * 1e15f;
      Console.WriteLine($"{value} + {additional} = {value + additional}");
   }
}
// The example displays the following output:
//    123.456 + 1.401298E-30 = 123.456
open System

let value = 123.456f
let additional = Single.Epsilon * 1e15f
printfn $"{value} + {additional} = {value + additional}"
// The example displays the following output:
//    123.456 + 1.401298E-30 = 123.456
Module Example
   Public Sub Main()
      Dim value As Single = 123.456
      Dim additional As Single = Single.Epsilon * 1e15
      Console.WriteLine($"{value} + {additional} = {value + additional}")
   End Sub
End Module
' The example displays the following output:
'   123.456 + 1.401298E-30 = 123.456

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

  • Dos números de coma flotante que parecen iguales para una precisión determinada podrían no compararse como iguales porque sus dígitos menos significativos sean diferentes. En el ejemplo siguiente, se agregan una serie de números y su total se compara con su total esperado. Aunque los dos valores parecen ser los mismos, una llamada al Equals método indica que no lo son.

    using System;
    
    public class Example
    {
       public static void Main()
       {
          Single[] values = { 10.01f, 2.88f, 2.88f, 2.88f, 9.0f };
          Single result = 27.65f;
          Single total = 0f;
          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 (27.65) does not equal the total (27.65).   
    //
    // 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.6500015) does not equal the total (27.65).
    
    let values = [| 10.01f; 2.88f; 2.88f; 2.88f; 9f |]
    let result = 27.65f
    let mutable total = 0f
    for value in values do
        total <- total + value
    
    if total.Equals result then
        printfn "The sum of the values equals the total."
    else
        printfn "The sum of the values ({total}) does not equal the total ({result})."
    // The example displays the following output:
    //      The sum of the values (27.65) does not equal the total (27.65).   
    //
    // 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.6500015) does not equal the total (27.65).
    
    Module Example
       Public Sub Main()
          Dim values() As Single = { 10.01, 2.88, 2.88, 2.88, 9.0 }
          Dim result As Single = 27.65
          Dim total As Single
          For Each value In values
             total += value
          Next
          If total.Equals(result) Then
             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) 
          End If     
       End Sub
    End Module
    ' The example displays the following output:
    '      The sum of the values (27.65) does not equal the total (27.65).   
    '
    ' 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 de la Console.WriteLine(String, Object, Object) instrucción de {0} y {1} a y {1:R} para mostrar todos los dígitos significativos de los dos Single valores, es claro que los dos valores no son iguales debido a {0:R} una pérdida de precisión durante las operaciones de suma. En este caso, el problema se puede resolver llamando al Math.Round(Double, Int32) método para redondear los Single valores a la precisión deseada antes de realizar la comparación.

  • Una operación matemática o de comparación que usa un número de punto flotante podría no producir el mismo resultado si se usa un número decimal, ya que el número de punto flotante binario podría no ser igual al número decimal. Un ejemplo anterior ilustraba esto mostrando el resultado de multiplicar .3 por 10 y agregar .3 a .3 nueve veces.

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

  • Un valor podría no redondear si hay un número de punto flotante implicado. Se dice un valor de ida y vuelta si una operación convierte un número de punto flotante original en otro formulario, una operación inversa transforma el formulario convertido en un número de punto flotante y el número de punto flotante final es igual al número de punto flotante original. El recorrido de ida y vuelta puede producir un error porque uno o varios dígitos menos significativos se pierden o cambian en una conversión. En el ejemplo siguiente, tres Single valores se convierten en cadenas y se guardan en un archivo. Como se muestra en la salida, aunque los valores parecen ser idénticos, 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(@".\Singles.dat");
          Single[] values = { 3.2f/1.11f, 1.0f/3f, (float) Math.PI };
          for (int ctr = 0; ctr < values.Length; ctr++) {
             sw.Write(values[ctr].ToString());
             if (ctr != values.Length - 1)
                sw.Write("|");
          }      
          sw.Close();
          
          Single[] restoredValues = new Single[values.Length];
          StreamReader sr = new StreamReader(@".\Singles.dat");
          string temp = sr.ReadToEnd();
          string[] tempStrings = temp.Split('|');
          for (int ctr = 0; ctr < tempStrings.Length; ctr++)
             restoredValues[ctr] = Single.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.882883 <> 2.882883
    //       0.3333333 <> 0.3333333
    //       3.141593 <> 3.141593
    
    open System
    open System.IO
    
    let values = [| 3.2f / 1.11f; 1f / 3f; MathF.PI |]
    
    do
        use sw = new StreamWriter(@".\Singles.dat")
        for i = 0 to values.Length - 1 do
            sw.Write(string values[i])
            if i <> values.Length - 1 then
                sw.Write "|"
    
    let restoredValues =
        use sr = new StreamReader(@".\Singles.dat")
        sr.ReadToEnd().Split '|'
        |> Array.map Single.Parse
    
    for i = 0 to values.Length - 1 do
        printfn $"""{values[i]} {if values[i].Equals restoredValues[i] then "=" else "<>"} {restoredValues[i]}"""
                        
    // The example displays the following output:
    //       2.882883 <> 2.882883
    //       0.3333333 <> 0.3333333
    //       3.141593 <> 3.141593
    
    Imports System.IO
    
    Module Example
       Public Sub Main()
          Dim sw As New StreamWriter(".\Singles.dat")
          Dim values() As Single = { 3.2/1.11, 1.0/3, CSng(Math.PI)  }
          For ctr As Integer = 0 To values.Length - 1
             sw.Write(values(ctr).ToString())
             If ctr <> values.Length - 1 Then sw.Write("|")
          Next      
          sw.Close()
          
          Dim restoredValues(values.Length - 1) As Single
          Dim sr As New StreamReader(".\Singles.dat")
          Dim temp As String = sr.ReadToEnd()
          Dim tempStrings() As String = temp.Split("|"c)
          For ctr As Integer = 0 To tempStrings.Length - 1
             restoredValues(ctr) = Single.Parse(tempStrings(ctr))   
          Next 
    
          For ctr As Integer = 0 To values.Length - 1
             Console.WriteLine("{0} {2} {1}", values(ctr), 
                               restoredValues(ctr),
                               If(values(ctr).Equals(restoredValues(ctr)), "=", "<>"))
          Next
       End Sub
    End Module
    ' The example displays the following output:
    '        2.882883 <> 2.882883
    '        0.3333333 <> 0.3333333
    '        3.141593 <> 3.141593
    

    En este caso, los valores se pueden redondear correctamente mediante la cadena de formato numérico estándar "G9" para conservar la precisión completa de Single los valores, como se muestra en el ejemplo siguiente.

    using System;
    using System.IO;
    
    public class Example
    {
       public static void Main()
       {
          StreamWriter sw = new StreamWriter(@".\Singles.dat");
          Single[] values = { 3.2f/1.11f, 1.0f/3f, (float) Math.PI };
          for (int ctr = 0; ctr < values.Length; ctr++) 
             sw.Write("{0:G9}{1}", values[ctr], ctr < values.Length - 1 ? "|" : "" );
          
          sw.Close();
          
          Single[] restoredValues = new Single[values.Length];
          StreamReader sr = new StreamReader(@".\Singles.dat");
          string temp = sr.ReadToEnd();
          string[] tempStrings = temp.Split('|');
          for (int ctr = 0; ctr < tempStrings.Length; ctr++)
             restoredValues[ctr] = Single.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.882883 = 2.882883
    //       0.3333333 = 0.3333333
    //       3.141593 = 3.141593
    
    open System
    open System.IO
    
    let values = [| 3.2f / 1.11f; 1f / 3f; MathF.PI |]
    
    do
        use sw = new StreamWriter(@".\Singles.dat")
        for i = 0 to values.Length - 1 do
            sw.Write $"""{values[i]:G9}{if i < values.Length - 1 then "|" else ""}"""
        
        
    let restoredValues =
        use sr = new StreamReader(@".\Singles.dat")
        sr.ReadToEnd().Split '|'
        |> Array.map Single.Parse
    
    for i = 0 to values.Length - 1 do
        printfn $"""{values[i]} {if values[i].Equals restoredValues[i] then "=" else "<>"} {restoredValues[i]}"""
    // The example displays the following output:
    //       2.882883 = 2.882883
    //       0.3333333 = 0.3333333
    //       3.141593 = 3.141593
    
    Imports System.IO
    
    Module Example
       Public Sub Main()
          Dim sw As New StreamWriter(".\Singles.dat")
          Dim values() As Single = { 3.2/1.11, 1.0/3, CSng(Math.PI)  }
          For ctr As Integer = 0 To values.Length - 1
             sw.Write("{0:G9}{1}", values(ctr), 
                      If(ctr < values.Length - 1, "|", ""))
          Next      
          sw.Close()
          
          Dim restoredValues(values.Length - 1) As Single
          Dim sr As New StreamReader(".\Singles.dat")
          Dim temp As String = sr.ReadToEnd()
          Dim tempStrings() As String = temp.Split("|"c)
          For ctr As Integer = 0 To tempStrings.Length - 1
             restoredValues(ctr) = Single.Parse(tempStrings(ctr))   
          Next 
    
          For ctr As Integer = 0 To values.Length - 1
             Console.WriteLine("{0} {2} {1}", values(ctr), 
                               restoredValues(ctr),
                               If(values(ctr).Equals(restoredValues(ctr)), "=", "<>"))
          Next
       End Sub
    End Module
    ' The example displays the following output:
    '       2.882883 = 2.882883
    '       0.3333333 = 0.3333333
    '       3.141593 = 3.141593
    
  • Single los valores tienen menos precisión que Double los valores. Un Single valor que se convierte en un valor aparentemente equivalente Double a menudo no es igual al Double valor debido a diferencias de precisión. En el ejemplo siguiente, el resultado de operaciones de división idénticas se asigna a un Double valor y un Single valor . Después de convertir el Single valor en , Doubleuna comparación de los dos valores muestra que son 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
    
    open System
    
    let value1 = 1. / 3.
    let sValue2 = 1f /3f
    
    let value2 = double sValue2
    printfn $"{value1:R} = {value2:R}: {value1.Equals value2}"
    // The example displays the following output:
    //        0.33333333333333331 = 0.3333333432674408: False
    
    Module Example
       Public Sub Main()
          Dim value1 As Double = 1/3
          Dim sValue2 As Single = 1/3
          Dim value2 As Double = CDbl(sValue2)
          Console.WriteLine("{0} = {1}: {2}", value1, value2, value1.Equals(value2))
       End Sub
    End Module
    ' The example displays the following output:
    '       0.33333333333333331 = 0.3333333432674408: False
    

    Para evitar este problema, use el Double tipo de datos en lugar del Single tipo de datos o use el Round método para que ambos valores tengan la misma precisión.

Prueba de igualdad

Para considerarse igual, dos Single valores deben representar valores idénticos. Sin embargo, debido a las diferencias de precisión entre los valores, o debido a una pérdida de precisión por uno o ambos valores, los valores de punto flotante que se espera que sean idénticos suelen ser desiguales debido a las diferencias en sus dígitos menos significativos. Como resultado, llama al Equals método para determinar si dos valores son iguales o llama al CompareTo método para determinar la relación entre dos Single valores, a menudo produce resultados inesperados. Esto es evidente en el ejemplo siguiente, donde dos valores aparentemente iguales Single resultan ser desiguales, porque el primer valor tiene 7 dígitos de precisión, mientras que el segundo valor tiene 9.

using System;

public class Example
{
   public static void Main()
   {
      float value1 = .3333333f;
      float value2 = 1.0f/3;
      Console.WriteLine("{0:R} = {1:R}: {2}", value1, value2, value1.Equals(value2));
   }
}
// The example displays the following output:
//        0.3333333 = 0.333333343: False
let value1 = 0.3333333f
let value2 = 1f / 3f
printfn $"{value1:R} = {value2:R}: {value1.Equals value2}"
// The example displays the following output:
//        0.3333333 = 0.333333343: False
Module Example
   Public Sub Main()
      Dim value1 As Single = .3333333
      Dim value2 As Single = 1/3
      Console.WriteLine("{0:R} = {1:R}: {2}", value1, value2, value1.Equals(value2))
   End Sub
End Module
' The example displays the following output:
'       0.3333333 = 0.333333343: False

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

using System;

public class Example
{
   public static void Main()
   {
      float value1 = 10.201438f;
      value1 = (float) Math.Sqrt((float) Math.Pow(value1, 2));
      float value2 = (float) Math.Pow((float) value1 * 3.51f, 2);
      value2 = ((float) Math.Sqrt(value2)) / 3.51f;
      Console.WriteLine("{0} = {1}: {2}\n", 
                        value1, value2, value1.Equals(value2)); 
      Console.WriteLine("{0:G9} = {1:G9}", value1, value2); 
   }
}
// The example displays the following output:
//       10.20144 = 10.20144: False
//       
//       10.201438 = 10.2014389
let value1 = 
    10.201438f ** 2f
    |> sqrt

let value2 =
   ((value1 * 3.51f) ** 2f |> sqrt) / 3.51f

printfn $"{value1} = {value2}: {value1.Equals value2}\n" 
printfn $"{value1:G9} = {value2:G9}"
// The example displays the following output:
//       10.20144 = 10.20144: False
//       
//       10.201438 = 10.2014389
Module Example
   Public Sub Main()
      Dim value1 As Single = 10.201438
      value1 = CSng(Math.Sqrt(CSng(Math.Pow(value1, 2))))
      Dim value2 As Single = CSng(Math.Pow(value1 * CSng(3.51), 2))
      value2 = CSng(Math.Sqrt(value2) / CSng(3.51))
      Console.WriteLine("{0} = {1}: {2}", 
                        value1, value2, value1.Equals(value2)) 
      Console.WriteLine()
      Console.WriteLine("{0:G9} = {1:G9}", value1, value2) 
   End Sub
End Module
' The example displays the following output:
'       10.20144 = 10.20144: False
'       
'       10.201438 = 10.2014389

En los casos en los que es probable que una pérdida de precisión afecte al resultado de una comparación, puede usar las técnicas siguientes en lugar de llamar al Equals método o CompareTo :

  • Llame al 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 usar este enfoque de modo que dos valores fraccionarios sean equivalentes.

    using System;
    
    public class Example
    {
       public static void Main()
       {
          float value1 = .3333333f;
          float value2 = 1.0f/3;
          int precision = 7;
          value1 = (float) Math.Round(value1, precision);
          value2 = (float) 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
    
    open System
    
    let value1 = 0.3333333f
    let value2 = 1f / 3f
    let precision = 7
    let value1r = Math.Round(float value1, precision) |> float32
    let value2r = Math.Round(float value2, precision) |> float32
    printfn $"{value1:R} = {value2:R}: {value1.Equals value2}"
    // The example displays the following output:
    //        0.3333333 = 0.3333333: True
    
    Module Example
       Public Sub Main()
          Dim value1 As Single = .3333333
          Dim value2 As Single = 1/3
          Dim precision As Integer = 7
          value1 = CSng(Math.Round(value1, precision))
          value2 = CSng(Math.Round(value2, precision))
          Console.WriteLine("{0:R} = {1:R}: {2}", value1, value2, value1.Equals(value2))
       End Sub
    End Module
    ' The example displays the following output:
    '       0.3333333 = 0.3333333: True
    

    El problema de precisión todavía se aplica al redondeo de valores de punto medio. Para obtener más información, vea el método Math.Round(Double, Int32, MidpointRounding).

  • Pruebe la igualdad aproximada en lugar de la igualdad. Esta técnica requiere que defina una cantidad absoluta por la que los dos valores pueden diferir, pero seguir siendo iguales, o que defina una cantidad relativa por la que el valor más pequeño pueda diverge del valor mayor.

    Advertencia

    Single.Epsilon a veces se usa como medida absoluta de la distancia entre dos Single valores al probar la igualdad. Sin embargo, Single.Epsilon mide el valor más pequeño posible al que se puede agregar o restar de un cuyo Single valor es cero. Para la mayoría de los valores positivos y negativos Single , el valor de Single.Epsilon es demasiado pequeño para detectarse. Por lo tanto, a excepción de los valores que son cero, no se recomienda su uso en las pruebas para comprobar si son iguales.

    En el ejemplo siguiente se usa el último enfoque para definir un IsApproximatelyEqual método que prueba la diferencia relativa entre dos valores. También contrasta el resultado de las llamadas al IsApproximatelyEqual método y al Equals(Single) método .

    using System;
    
    public class Example
    {
       public static void Main()
       {
          float one1 = .1f * 10;
          float one2 = 0f;
          for (int ctr = 1; ctr <= 10; ctr++)
             one2 += .1f;
    
          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, .000001f));   
       }
    
       static bool IsApproximatelyEqual(float value1, float value2, float 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 = 1.00000012: False
    //       1 is approximately equal to 1.00000012: True
    
    open System
    
    let isApproximatelyEqual value1 value2 epsilon =
        // If they are equal anyway, just return True.
        if value1.Equals value2 then 
            true
        // Handle NaN, Infinity.
        elif Single.IsInfinity value1 || Single.IsNaN value1 then
            value1.Equals value2
        elif Single.IsInfinity value2 || Single.IsNaN value2 then
            value1.Equals value2
        else
            // Handle zero to avoid division by zero
            let divisor = max value1 value2
            let divisor = 
                if divisor.Equals 0 then
                    min value1 value2
                else divisor
            abs (value1 - value2) / divisor <= epsilon           
    
    
    let one1 = 0.1f * 10f
    let mutable one2 = 0f
    for _ = 1 to 10 do
       one2 <- one2 + 0.1f
    
    printfn $"{one1:R} = {one2:R}: {one1.Equals one2}"
    printfn $"{one1:R} is approximately equal to {one2:R}: {isApproximatelyEqual one1 one2 0.000001f}" 
    // The example displays the following output:
    //       1 = 1.00000012: False
    //       1 is approximately equal to 1.00000012: True
    
    Module Example
       Public Sub Main()
          Dim one1 As Single = .1 * 10
          Dim one2 As Single = 0
          For ctr As Integer = 1 To 10
             one2 += CSng(.1)
          Next
          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, .000001))   
       End Sub
    
       Function IsApproximatelyEqual(value1 As Single, value2 As Single, 
                                     epsilon As Single) As Boolean
          ' If they are equal anyway, just return True.
          If value1.Equals(value2) Then Return True
          
          ' Handle NaN, Infinity.
          If Single.IsInfinity(value1) Or Single.IsNaN(value1) Then
             Return value1.Equals(value2)
          Else If Single.IsInfinity(value2) Or Single.IsNaN(value2)
             Return value1.Equals(value2)
          End If
          
          ' Handle zero to avoid division by zero
          Dim divisor As Single = Math.Max(value1, value2)
          If divisor.Equals(0) Then
             divisor = Math.Min(value1, value2)
          End If 
          
          Return Math.Abs(value1 - value2)/divisor <= epsilon           
       End Function
    End Module
    ' The example displays the following output:
    '       1 = 1.00000012: False
    '       1 is approximately equal to 1.00000012: True
    

Excepciones y valores de punto flotante

Las operaciones con valores de punto flotante no inician excepciones, a diferencia de las operaciones con tipos enteros, que inician excepciones en casos de operaciones ilegales, como la división por cero o el desbordamiento. En su lugar, en estas situaciones, el resultado de una operación de punto flotante es cero, infinito positivo, infinito negativo o no 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 de punto flotante muy pequeños, como se muestra en el ejemplo siguiente.

    using System;
    
    public class Example
    {
       public static void Main()
       {
          float value1 = 1.163287e-36f;
          float value2 = 9.164234e-25f;
          float result = value1 * value2;
          Console.WriteLine("{0} * {1} = {2}", value1, value2, result);
          Console.WriteLine("{0} = 0: {1}", result, result.Equals(0.0f));
       }
    }
    // The example displays the following output:
    //       1.163287E-36 * 9.164234E-25 = 0
    //       0 = 0: True
    
    let value1 = 1.163287e-36f
    let value2 = 9.164234e-25f
    let result = value1 * value2
    printfn $"{value1} * {value2} = {result}"
    printfn $"{result} = 0: {result.Equals(0f)}"
    // The example displays the following output:
    //       1.163287E-36 * 9.164234E-25 = 0
    //       0 = 0: True
    
    Module Example
       Public Sub Main()
          Dim value1 As Single = 1.163287e-36
          Dim value2 As Single = 9.164234e-25
          Dim result As Single = value1 * value2
          Console.WriteLine("{0} * {1} = {2:R}", value1, value2, result)
          Console.WriteLine("{0} = 0: {1}", result, result.Equals(0))
       End Sub
    End Module
    ' The example displays the following output:
    '       1.163287E-36 * 9.164234E-25 = 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 Single.MaxValue es PositiveInfinityy el resultado de una operación que se desborda Single.MinValue es NegativeInfinity, como se muestra en el ejemplo siguiente.

    using System;
    
    public class Example
    {
       public static void Main()
       {
          float value1 = 3.065e35f;
          float value2 = 6.9375e32f;
          float result = value1 * value2;
          Console.WriteLine("PositiveInfinity: {0}", 
                             Single.IsPositiveInfinity(result));
          Console.WriteLine("NegativeInfinity: {0}\n", 
                            Single.IsNegativeInfinity(result));
    
          value1 = -value1;
          result = value1 * value2;
          Console.WriteLine("PositiveInfinity: {0}", 
                             Single.IsPositiveInfinity(result));
          Console.WriteLine("NegativeInfinity: {0}", 
                            Single.IsNegativeInfinity(result));
       }
    }                                                                 
    
    // The example displays the following output:
    //       PositiveInfinity: True
    //       NegativeInfinity: False
    //       
    //       PositiveInfinity: False
    //       NegativeInfinity: True
    
    open System
    
    let value1 = 3.065e35f
    let value2 = 6.9375e32f
    let result = value1 * value2
    printfn $"PositiveInfinity: {Single.IsPositiveInfinity result}" 
    printfn $"NegativeInfinity: {Single.IsNegativeInfinity result}\n"
    
    let value3 = -value1
    let result2 = value3 * value2
    printfn $"PositiveInfinity: {Single.IsPositiveInfinity result}" 
    printfn $"NegativeInfinity: {Single.IsNegativeInfinity result}" 
    
    // The example displays the following output:
    //       PositiveInfinity: True
    //       NegativeInfinity: False
    //       
    //       PositiveInfinity: False
    //       NegativeInfinity: True
    
    Module Example
       Public Sub Main()
          Dim value1 As Single = 3.065e35
          Dim value2 As Single = 6.9375e32
          Dim result As Single = value1 * value2
          Console.WriteLine("PositiveInfinity: {0}", 
                             Single.IsPositiveInfinity(result))
          Console.WriteLine("NegativeInfinity: {0}", 
                            Single.IsNegativeInfinity(result))
          Console.WriteLine()                  
          value1 = -value1
          result = value1 * value2
          Console.WriteLine("PositiveInfinity: {0}", 
                             Single.IsPositiveInfinity(result))
          Console.WriteLine("NegativeInfinity: {0}", 
                            Single.IsNegativeInfinity(result))
       End Sub
    End Module
    ' The example displays the following output:
    '       PositiveInfinity: True
    '       NegativeInfinity: False
    '       
    '       PositiveInfinity: False
    '       NegativeInfinity: True
    

    PositiveInfinity también resulta de una división por cero con un dividendo positivo y NegativeInfinity resultados de una división por cero con un dividendo negativo.

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

    • División por cero con un dividendo de cero. Tenga en cuenta que otros casos de división por cero dan como resultado o PositiveInfinity NegativeInfinity.

    • Cualquier operación de punto flotante con entrada no válida. Por ejemplo, si intenta buscar la raíz cuadrada de un valor negativo, devuelve NaN.

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

Conversiones de tipos y la estructura Single

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

En la tabla siguiente se enumeran las posibles conversiones de un valor de los otros tipos numéricos primitivos a un Single valor, también indica si la conversión está ampliando o estrechando y si el resultado Single puede tener menos precisión que el valor original.

Conversión de Ampliación y restricción Posible pérdida de precisión
Byte Widening No
Decimal Widening

Tenga en cuenta que C# requiere un operador de conversión.
Sí. Decimal admite 29 dígitos decimales de precisión; Single admite 9.
Double Estrechamiento; Los valores fuera del intervalo se convierten en Double.NegativeInfinity o Double.PositiveInfinity. Sí. Double admite 17 dígitos decimales de precisión; Single admite 9.
Int16 Widening No
Int32 Widening Sí. Int32 admite 10 dígitos decimales de precisión; Single admite 9.
Int64 Widening Sí. Int64 admite 19 dígitos decimales de precisión; Single admite 9.
SByte Widening No
UInt16 Widening No
UInt32 Widening Sí. UInt32 admite 10 dígitos decimales de precisión; Single admite 9.
UInt64 Widening Sí. Int64 admite 20 dígitos decimales de precisión; Single admite 9.

En el ejemplo siguiente se convierte el valor mínimo o máximo de otros tipos numéricos primitivos en un Single valor.

using System;

public class Example
{
   public static void Main()
   {
      dynamic[] values = { Byte.MinValue, Byte.MaxValue, Decimal.MinValue,
                           Decimal.MaxValue, Double.MinValue, Double.MaxValue,
                           Int16.MinValue, Int16.MaxValue, Int32.MinValue,
                           Int32.MaxValue, Int64.MinValue, Int64.MaxValue,
                           SByte.MinValue, SByte.MaxValue, UInt16.MinValue,
                           UInt16.MaxValue, UInt32.MinValue, UInt32.MaxValue,
                           UInt64.MinValue, UInt64.MaxValue };
      float sngValue;
      foreach (var value in values) {
         if (value.GetType() == typeof(Decimal) ||
             value.GetType() == typeof(Double))
            sngValue = (float) value;
         else
            sngValue = value;
         Console.WriteLine("{0} ({1}) --> {2:R} ({3})",
                           value, value.GetType().Name,
                           sngValue, sngValue.GetType().Name);
      }
   }
}
// The example displays the following output:
//       0 (Byte) --> 0 (Single)
//       255 (Byte) --> 255 (Single)
//       -79228162514264337593543950335 (Decimal) --> -7.92281625E+28 (Single)
//       79228162514264337593543950335 (Decimal) --> 7.92281625E+28 (Single)
//       -1.79769313486232E+308 (Double) --> -Infinity (Single)
//       1.79769313486232E+308 (Double) --> Infinity (Single)
//       -32768 (Int16) --> -32768 (Single)
//       32767 (Int16) --> 32767 (Single)
//       -2147483648 (Int32) --> -2.14748365E+09 (Single)
//       2147483647 (Int32) --> 2.14748365E+09 (Single)
//       -9223372036854775808 (Int64) --> -9.223372E+18 (Single)
//       9223372036854775807 (Int64) --> 9.223372E+18 (Single)
//       -128 (SByte) --> -128 (Single)
//       127 (SByte) --> 127 (Single)
//       0 (UInt16) --> 0 (Single)
//       65535 (UInt16) --> 65535 (Single)
//       0 (UInt32) --> 0 (Single)
//       4294967295 (UInt32) --> 4.2949673E+09 (Single)
//       0 (UInt64) --> 0 (Single)
//       18446744073709551615 (UInt64) --> 1.84467441E+19 (Single)
open System

let values: obj list = 
    [ Byte.MinValue; Byte.MaxValue; Decimal.MinValue
      Decimal.MaxValue; Double.MinValue; Double.MaxValue
      Int16.MinValue; Int16.MaxValue; Int32.MinValue
      Int32.MaxValue; Int64.MinValue; Int64.MaxValue
      SByte.MinValue; SByte.MaxValue; UInt16.MinValue
      UInt16.MaxValue; UInt32.MinValue; UInt32.MaxValue
      UInt64.MinValue; UInt64.MaxValue ]

for value in values do
    let sngValue = 
        match value with
        | :? byte as v -> float32 v
        | :? decimal as v -> float32 v
        | :? double as v -> float32 v
        | :? int16 as v -> float32 v
        | :? int as v -> float32 v
        | :? int64 as v -> float32 v
        | :? int8 as v -> float32 v
        | :? uint16 as v -> float32 v
        | :? uint as v -> float32 v
        | :? uint64 as v -> float32 v
        | _ -> raise (NotImplementedException "Unknown Type")
    printfn $"{value} ({value.GetType().Name}) --> {sngValue:R} ({sngValue.GetType().Name})"
// The example displays the following output:
//       0 (Byte) --> 0 (Single)
//       255 (Byte) --> 255 (Single)
//       -79228162514264337593543950335 (Decimal) --> -7.92281625E+28 (Single)
//       79228162514264337593543950335 (Decimal) --> 7.92281625E+28 (Single)
//       -1.79769313486232E+308 (Double) --> -Infinity (Single)
//       1.79769313486232E+308 (Double) --> Infinity (Single)
//       -32768 (Int16) --> -32768 (Single)
//       32767 (Int16) --> 32767 (Single)
//       -2147483648 (Int32) --> -2.14748365E+09 (Single)
//       2147483647 (Int32) --> 2.14748365E+09 (Single)
//       -9223372036854775808 (Int64) --> -9.223372E+18 (Single)
//       9223372036854775807 (Int64) --> 9.223372E+18 (Single)
//       -128 (SByte) --> -128 (Single)
//       127 (SByte) --> 127 (Single)
//       0 (UInt16) --> 0 (Single)
//       65535 (UInt16) --> 65535 (Single)
//       0 (UInt32) --> 0 (Single)
//       4294967295 (UInt32) --> 4.2949673E+09 (Single)
//       0 (UInt64) --> 0 (Single)
//       18446744073709551615 (UInt64) --> 1.84467441E+19 (Single)
Module Example
   Public Sub Main()
      Dim values() As Object = { Byte.MinValue, Byte.MaxValue, Decimal.MinValue,
                                 Decimal.MaxValue, Double.MinValue, Double.MaxValue,
                                 Int16.MinValue, Int16.MaxValue, Int32.MinValue,
                                 Int32.MaxValue, Int64.MinValue, Int64.MaxValue,
                                 SByte.MinValue, SByte.MaxValue, UInt16.MinValue,
                                 UInt16.MaxValue, UInt32.MinValue, UInt32.MaxValue,
                                 UInt64.MinValue, UInt64.MaxValue }
      Dim sngValue As Single
      For Each value In values
         If value.GetType() = GetType(Double) Then
            sngValue = CSng(value)
         Else
            sngValue = value
         End If
         Console.WriteLine("{0} ({1}) --> {2:R} ({3})",
                           value, value.GetType().Name,
                           sngValue, sngValue.GetType().Name)
      Next
   End Sub
End Module
' The example displays the following output:
'       0 (Byte) --> 0 (Single)
'       255 (Byte) --> 255 (Single)
'       -79228162514264337593543950335 (Decimal) --> -7.92281625E+28 (Single)
'       79228162514264337593543950335 (Decimal) --> 7.92281625E+28 (Single)
'       -1.79769313486232E+308 (Double) --> -Infinity (Single)
'       1.79769313486232E+308 (Double) --> Infinity (Single)
'       -32768 (Int16) --> -32768 (Single)
'       32767 (Int16) --> 32767 (Single)
'       -2147483648 (Int32) --> -2.14748365E+09 (Single)
'       2147483647 (Int32) --> 2.14748365E+09 (Single)
'       -9223372036854775808 (Int64) --> -9.223372E+18 (Single)
'       9223372036854775807 (Int64) --> 9.223372E+18 (Single)
'       -128 (SByte) --> -128 (Single)
'       127 (SByte) --> 127 (Single)
'       0 (UInt16) --> 0 (Single)
'       65535 (UInt16) --> 65535 (Single)
'       0 (UInt32) --> 0 (Single)
'       4294967295 (UInt32) --> 4.2949673E+09 (Single)
'       0 (UInt64) --> 0 (Single)
'       18446744073709551615 (UInt64) --> 1.84467441E+19 (Single)

Además, los Double valores Double.NaN, Double.PositiveInfinityy convierten Double.NegativeInfinity en Single.NaN, Single.PositiveInfinityy Single.NegativeInfinity, respectivamente.

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

La conversión de un Single valor a un Double es una conversión de ampliación. La conversión puede provocar una pérdida de precisión si el Double tipo no tiene una representación precisa para el Single valor.

La conversión de un Single valor a un valor de cualquier tipo de datos numérico primitivo distinto de es Double una conversión de restricción y requiere un operador de conversión (en C#) o un método de conversión (en Visual Basic). Los valores que están fuera del intervalo del tipo de datos de destino, que se definen mediante las propiedades y MaxValue del tipo MinValue de destino, se comportan como se muestra en la tabla siguiente.

Tipo de destino Resultado
Cualquier tipo entero Excepción OverflowException si la conversión se produce 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 el valor se desborda.
Decimal Excepción OverflowException ,

Además, Single.NaN, Single.PositiveInfinityy Single.NegativeInfinity inician una OverflowException para conversiones en enteros en un contexto comprobado, pero estos valores se desbordan cuando se convierten en enteros en un contexto no comprobado. En el caso de las conversiones en Decimal, siempre inician una OverflowExceptionexcepción . Para las conversiones a Double, convierten en Double.NaN, Double.PositiveInfinityy Double.NegativeInfinity, respectivamente.

Tenga en cuenta que una pérdida de precisión puede resultar de convertir un Single valor en otro tipo numérico. En el caso de convertir valores no enterosSingle, como se muestra en la salida del ejemplo, se pierde el componente fraccional cuando el Single valor se redondea (como en Visual Basic) o truncado (como en C# y F#). Para las conversiones a Decimal valores, es posible que el Single valor no tenga una representación precisa en el tipo de datos de destino.

En el ejemplo siguiente se convierte una serie de Single valores en otros tipos numéricos. Las conversiones se producen en un contexto comprobado en Visual Basic (valor predeterminado), en C# (debido a la palabra clave checked) y en F# (debido a la open Checked instrucción ). La salida del ejemplo muestra el resultado de las conversiones en un contexto no comprobado. Puede realizar conversiones en un contexto no comprobado en Visual Basic mediante la compilación con el /removeintchecks+ modificador del compilador, en C# comentando la checked instrucción y en F# comentando la open Checked instrucción.

using System;

public class Example
{
   public static void Main()
   {
      float[] values = { Single.MinValue, -67890.1234f, -12345.6789f,
                         12345.6789f, 67890.1234f, Single.MaxValue,
                         Single.NaN, Single.PositiveInfinity,
                         Single.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);
            }

            Double dblValue = value;
            Console.WriteLine("{0} ({1}) --> {2} ({3})",
                              value, value.GetType().Name,
                              dblValue, dblValue.GetType().Name);
            Console.WriteLine();
         }
      }
   }
}
// The example displays the following output for conversions performed
// in a checked context:
//       Unable to convert -3.402823E+38 to Int64.
//       Unable to convert -3.402823E+38 to UInt64.
//       Unable to convert -3.402823E+38 to Decimal.
//       -3.402823E+38 (Single) --> -3.40282346638529E+38 (Double)
//
//       -67890.13 (Single) --> -67890 (0xFFFFFFFFFFFEF6CE) (Int64)
//       Unable to convert -67890.13 to UInt64.
//       -67890.13 (Single) --> -67890.12 (Decimal)
//       -67890.13 (Single) --> -67890.125 (Double)
//
//       -12345.68 (Single) --> -12345 (0xFFFFFFFFFFFFCFC7) (Int64)
//       Unable to convert -12345.68 to UInt64.
//       -12345.68 (Single) --> -12345.68 (Decimal)
//       -12345.68 (Single) --> -12345.6787109375 (Double)
//
//       12345.68 (Single) --> 12345 (0x0000000000003039) (Int64)
//       12345.68 (Single) --> 12345 (0x0000000000003039) (UInt64)
//       12345.68 (Single) --> 12345.68 (Decimal)
//       12345.68 (Single) --> 12345.6787109375 (Double)
//
//       67890.13 (Single) --> 67890 (0x0000000000010932) (Int64)
//       67890.13 (Single) --> 67890 (0x0000000000010932) (UInt64)
//       67890.13 (Single) --> 67890.12 (Decimal)
//       67890.13 (Single) --> 67890.125 (Double)
//
//       Unable to convert 3.402823E+38 to Int64.
//       Unable to convert 3.402823E+38 to UInt64.
//       Unable to convert 3.402823E+38 to Decimal.
//       3.402823E+38 (Single) --> 3.40282346638529E+38 (Double)
//
//       Unable to convert NaN to Int64.
//       Unable to convert NaN to UInt64.
//       Unable to convert NaN to Decimal.
//       NaN (Single) --> NaN (Double)
//
//       Unable to convert Infinity to Int64.
//       Unable to convert Infinity to UInt64.
//       Unable to convert Infinity to Decimal.
//       Infinity (Single) --> Infinity (Double)
//
//       Unable to convert -Infinity to Int64.
//       Unable to convert -Infinity to UInt64.
//       Unable to convert -Infinity to Decimal.
//       -Infinity (Single) --> -Infinity (Double)
// The example displays the following output for conversions performed
// in an unchecked context:
//       -3.402823E+38 (Single) --> -9223372036854775808 (0x8000000000000000) (Int64)
//       -3.402823E+38 (Single) --> 9223372036854775808 (0x8000000000000000) (UInt64)
//       Unable to convert -3.402823E+38 to Decimal.
//       -3.402823E+38 (Single) --> -3.40282346638529E+38 (Double)
//
//       -67890.13 (Single) --> -67890 (0xFFFFFFFFFFFEF6CE) (Int64)
//       -67890.13 (Single) --> 18446744073709483726 (0xFFFFFFFFFFFEF6CE) (UInt64)
//       -67890.13 (Single) --> -67890.12 (Decimal)
//       -67890.13 (Single) --> -67890.125 (Double)
//
//       -12345.68 (Single) --> -12345 (0xFFFFFFFFFFFFCFC7) (Int64)
//       -12345.68 (Single) --> 18446744073709539271 (0xFFFFFFFFFFFFCFC7) (UInt64)
//       -12345.68 (Single) --> -12345.68 (Decimal)
//       -12345.68 (Single) --> -12345.6787109375 (Double)
//
//       12345.68 (Single) --> 12345 (0x0000000000003039) (Int64)
//       12345.68 (Single) --> 12345 (0x0000000000003039) (UInt64)
//       12345.68 (Single) --> 12345.68 (Decimal)
//       12345.68 (Single) --> 12345.6787109375 (Double)
//
//       67890.13 (Single) --> 67890 (0x0000000000010932) (Int64)
//       67890.13 (Single) --> 67890 (0x0000000000010932) (UInt64)
//       67890.13 (Single) --> 67890.12 (Decimal)
//       67890.13 (Single) --> 67890.125 (Double)
//
//       3.402823E+38 (Single) --> -9223372036854775808 (0x8000000000000000) (Int64)
//       3.402823E+38 (Single) --> 0 (0x0000000000000000) (UInt64)
//       Unable to convert 3.402823E+38 to Decimal.
//       3.402823E+38 (Single) --> 3.40282346638529E+38 (Double)
//
//       NaN (Single) --> -9223372036854775808 (0x8000000000000000) (Int64)
//       NaN (Single) --> 0 (0x0000000000000000) (UInt64)
//       Unable to convert NaN to Decimal.
//       NaN (Single) --> NaN (Double)
//
//       Infinity (Single) --> -9223372036854775808 (0x8000000000000000) (Int64)
//       Infinity (Single) --> 0 (0x0000000000000000) (UInt64)
//       Unable to convert Infinity to Decimal.
//       Infinity (Single) --> Infinity (Double)
//
//       -Infinity (Single) --> -9223372036854775808 (0x8000000000000000) (Int64)
//       -Infinity (Single) --> 9223372036854775808 (0x8000000000000000) (UInt64)
//       Unable to convert -Infinity to Decimal.
//       -Infinity (Single) --> -Infinity (Double)
open System
open Checked

let values = 
    [ Single.MinValue; -67890.1234f; -12345.6789f
      12345.6789f; 67890.1234f; Single.MaxValue
      Single.NaN; Single.PositiveInfinity
      Single.NegativeInfinity ]

for value in values do
    try
        let lValue = int64 value
        printfn $"{value} ({value.GetType().Name}) --> {lValue} (0x{lValue:X16}) ({lValue.GetType().Name})"
    with :? OverflowException ->
        printfn $"Unable to convert {value} to Int64."
    try
        let ulValue = uint64 value
        printfn $"{value} ({value.GetType().Name}) --> {ulValue} (0x{ulValue:X16}) ({ulValue.GetType().Name})"
    with :? OverflowException ->
        printfn $"Unable to convert {value} to UInt64."
    try
        let dValue = decimal value
        printfn $"{value} ({value.GetType().Name}) --> {dValue} ({dValue.GetType().Name})"
    with :? OverflowException ->
        printfn $"Unable to convert {value} to Decimal."

    let dblValue = double value
    printfn $"{value} ({value.GetType().Name}) --> {dblValue} ({dblValue.GetType().Name})\n"
// The example displays the following output for conversions performed
// in a checked context:
//       Unable to convert -3.402823E+38 to Int64.
//       Unable to convert -3.402823E+38 to UInt64.
//       Unable to convert -3.402823E+38 to Decimal.
//       -3.402823E+38 (Single) --> -3.40282346638529E+38 (Double)
//
//       -67890.13 (Single) --> -67890 (0xFFFFFFFFFFFEF6CE) (Int64)
//       Unable to convert -67890.13 to UInt64.
//       -67890.13 (Single) --> -67890.12 (Decimal)
//       -67890.13 (Single) --> -67890.125 (Double)
//
//       -12345.68 (Single) --> -12345 (0xFFFFFFFFFFFFCFC7) (Int64)
//       Unable to convert -12345.68 to UInt64.
//       -12345.68 (Single) --> -12345.68 (Decimal)
//       -12345.68 (Single) --> -12345.6787109375 (Double)
//
//       12345.68 (Single) --> 12345 (0x0000000000003039) (Int64)
//       12345.68 (Single) --> 12345 (0x0000000000003039) (UInt64)
//       12345.68 (Single) --> 12345.68 (Decimal)
//       12345.68 (Single) --> 12345.6787109375 (Double)
//
//       67890.13 (Single) --> 67890 (0x0000000000010932) (Int64)
//       67890.13 (Single) --> 67890 (0x0000000000010932) (UInt64)
//       67890.13 (Single) --> 67890.12 (Decimal)
//       67890.13 (Single) --> 67890.125 (Double)
//
//       Unable to convert 3.402823E+38 to Int64.
//       Unable to convert 3.402823E+38 to UInt64.
//       Unable to convert 3.402823E+38 to Decimal.
//       3.402823E+38 (Single) --> 3.40282346638529E+38 (Double)
//
//       Unable to convert NaN to Int64.
//       Unable to convert NaN to UInt64.
//       Unable to convert NaN to Decimal.
//       NaN (Single) --> NaN (Double)
//
//       Unable to convert Infinity to Int64.
//       Unable to convert Infinity to UInt64.
//       Unable to convert Infinity to Decimal.
//       Infinity (Single) --> Infinity (Double)
//
//       Unable to convert -Infinity to Int64.
//       Unable to convert -Infinity to UInt64.
//       Unable to convert -Infinity to Decimal.
//       -Infinity (Single) --> -Infinity (Double)
// The example displays the following output for conversions performed
// in an unchecked context:
//       -3.402823E+38 (Single) --> -9223372036854775808 (0x8000000000000000) (Int64)
//       -3.402823E+38 (Single) --> 9223372036854775808 (0x8000000000000000) (UInt64)
//       Unable to convert -3.402823E+38 to Decimal.
//       -3.402823E+38 (Single) --> -3.40282346638529E+38 (Double)
//
//       -67890.13 (Single) --> -67890 (0xFFFFFFFFFFFEF6CE) (Int64)
//       -67890.13 (Single) --> 18446744073709483726 (0xFFFFFFFFFFFEF6CE) (UInt64)
//       -67890.13 (Single) --> -67890.12 (Decimal)
//       -67890.13 (Single) --> -67890.125 (Double)
//
//       -12345.68 (Single) --> -12345 (0xFFFFFFFFFFFFCFC7) (Int64)
//       -12345.68 (Single) --> 18446744073709539271 (0xFFFFFFFFFFFFCFC7) (UInt64)
//       -12345.68 (Single) --> -12345.68 (Decimal)
//       -12345.68 (Single) --> -12345.6787109375 (Double)
//
//       12345.68 (Single) --> 12345 (0x0000000000003039) (Int64)
//       12345.68 (Single) --> 12345 (0x0000000000003039) (UInt64)
//       12345.68 (Single) --> 12345.68 (Decimal)
//       12345.68 (Single) --> 12345.6787109375 (Double)
//
//       67890.13 (Single) --> 67890 (0x0000000000010932) (Int64)
//       67890.13 (Single) --> 67890 (0x0000000000010932) (UInt64)
//       67890.13 (Single) --> 67890.12 (Decimal)
//       67890.13 (Single) --> 67890.125 (Double)
//
//       3.402823E+38 (Single) --> -9223372036854775808 (0x8000000000000000) (Int64)
//       3.402823E+38 (Single) --> 0 (0x0000000000000000) (UInt64)
//       Unable to convert 3.402823E+38 to Decimal.
//       3.402823E+38 (Single) --> 3.40282346638529E+38 (Double)
//
//       NaN (Single) --> -9223372036854775808 (0x8000000000000000) (Int64)
//       NaN (Single) --> 0 (0x0000000000000000) (UInt64)
//       Unable to convert NaN to Decimal.
//       NaN (Single) --> NaN (Double)
//
//       Infinity (Single) --> -9223372036854775808 (0x8000000000000000) (Int64)
//       Infinity (Single) --> 0 (0x0000000000000000) (UInt64)
//       Unable to convert Infinity to Decimal.
//       Infinity (Single) --> Infinity (Double)
//
//       -Infinity (Single) --> -9223372036854775808 (0x8000000000000000) (Int64)
//       -Infinity (Single) --> 9223372036854775808 (0x8000000000000000) (UInt64)
//       Unable to convert -Infinity to Decimal.
//       -Infinity (Single) --> -Infinity (Double)
Module Example
   Public Sub Main()
      Dim values() As Single = { Single.MinValue, -67890.1234, -12345.6789,
                                 12345.6789, 67890.1234, Single.MaxValue,
                                 Single.NaN, Single.PositiveInfinity,
                                 Single.NegativeInfinity }
      For Each value In values
         Try
             Dim lValue As Long = CLng(value)
             Console.WriteLine("{0} ({1}) --> {2} (0x{2:X16}) ({3})",
                               value, value.GetType().Name,
                               lValue, lValue.GetType().Name)
         Catch e As OverflowException
            Console.WriteLine("Unable to convert {0} to Int64.", value)
         End Try
         Try
             Dim ulValue As UInt64 = CULng(value)
             Console.WriteLine("{0} ({1}) --> {2} (0x{2:X16}) ({3})",
                               value, value.GetType().Name,
                               ulValue, ulValue.GetType().Name)
         Catch e As OverflowException
            Console.WriteLine("Unable to convert {0} to UInt64.", value)
         End Try
         Try
             Dim dValue As Decimal = CDec(value)
             Console.WriteLine("{0} ({1}) --> {2} ({3})",
                               value, value.GetType().Name,
                               dValue, dValue.GetType().Name)
         Catch e As OverflowException
            Console.WriteLine("Unable to convert {0} to Decimal.", value)
         End Try

         Dim dblValue As Double = value
         Console.WriteLine("{0} ({1}) --> {2} ({3})",
                           value, value.GetType().Name,
                           dblValue, dblValue.GetType().Name)
         Console.WriteLine()
      Next
   End Sub
End Module
' The example displays the following output for conversions performed
' in a checked context:
'       Unable to convert -3.402823E+38 to Int64.
'       Unable to convert -3.402823E+38 to UInt64.
'       Unable to convert -3.402823E+38 to Decimal.
'       -3.402823E+38 (Single) --> -3.40282346638529E+38 (Double)
'
'       -67890.13 (Single) --> -67890 (0xFFFFFFFFFFFEF6CE) (Int64)
'       Unable to convert -67890.13 to UInt64.
'       -67890.13 (Single) --> -67890.12 (Decimal)
'       -67890.13 (Single) --> -67890.125 (Double)
'
'       -12345.68 (Single) --> -12346 (0xFFFFFFFFFFFFCFC6) (Int64)
'       Unable to convert -12345.68 to UInt64.
'       -12345.68 (Single) --> -12345.68 (Decimal)
'       -12345.68 (Single) --> -12345.6787109375 (Double)
'
'       12345.68 (Single) --> 12346 (0x000000000000303A) (Int64)
'       12345.68 (Single) --> 12346 (0x000000000000303A) (UInt64)
'       12345.68 (Single) --> 12345.68 (Decimal)
'       12345.68 (Single) --> 12345.6787109375 (Double)
'
'       67890.13 (Single) --> 67890 (0x0000000000010932) (Int64)
'       67890.13 (Single) --> 67890 (0x0000000000010932) (UInt64)
'       67890.13 (Single) --> 67890.12 (Decimal)
'       67890.13 (Single) --> 67890.125 (Double)
'
'       Unable to convert 3.402823E+38 to Int64.
'       Unable to convert 3.402823E+38 to UInt64.
'       Unable to convert 3.402823E+38 to Decimal.
'       3.402823E+38 (Single) --> 3.40282346638529E+38 (Double)
'
'       Unable to convert NaN to Int64.
'       Unable to convert NaN to UInt64.
'       Unable to convert NaN to Decimal.
'       NaN (Single) --> NaN (Double)
'
'       Unable to convert Infinity to Int64.
'       Unable to convert Infinity to UInt64.
'       Unable to convert Infinity to Decimal.
'       Infinity (Single) --> Infinity (Double)
'
'       Unable to convert -Infinity to Int64.
'       Unable to convert -Infinity to UInt64.
'       Unable to convert -Infinity to Decimal.
'       -Infinity (Single) --> -Infinity (Double)
' The example displays the following output for conversions performed
' in an unchecked context:
'       -3.402823E+38 (Single) --> -9223372036854775808 (0x8000000000000000) (Int64)
'       -3.402823E+38 (Single) --> 9223372036854775808 (0x8000000000000000) (UInt64)
'       Unable to convert -3.402823E+38 to Decimal.
'       -3.402823E+38 (Single) --> -3.40282346638529E+38 (Double)
'
'       -67890.13 (Single) --> -67890 (0xFFFFFFFFFFFEF6CE) (Int64)
'       -67890.13 (Single) --> 18446744073709483726 (0xFFFFFFFFFFFEF6CE) (UInt64)
'       -67890.13 (Single) --> -67890.12 (Decimal)
'       -67890.13 (Single) --> -67890.125 (Double)
'
'       -12345.68 (Single) --> -12346 (0xFFFFFFFFFFFFCFC6) (Int64)
'       -12345.68 (Single) --> 18446744073709539270 (0xFFFFFFFFFFFFCFC6) (UInt64)
'       -12345.68 (Single) --> -12345.68 (Decimal)
'       -12345.68 (Single) --> -12345.6787109375 (Double)
'
'       12345.68 (Single) --> 12346 (0x000000000000303A) (Int64)
'       12345.68 (Single) --> 12346 (0x000000000000303A) (UInt64)
'       12345.68 (Single) --> 12345.68 (Decimal)
'       12345.68 (Single) --> 12345.6787109375 (Double)
'
'       67890.13 (Single) --> 67890 (0x0000000000010932) (Int64)
'       67890.13 (Single) --> 67890 (0x0000000000010932) (UInt64)
'       67890.13 (Single) --> 67890.12 (Decimal)
'       67890.13 (Single) --> 67890.125 (Double)
'
'       3.402823E+38 (Single) --> -9223372036854775808 (0x8000000000000000) (Int64)
'       3.402823E+38 (Single) --> 0 (0x0000000000000000) (UInt64)
'       Unable to convert 3.402823E+38 to Decimal.
'       3.402823E+38 (Single) --> 3.40282346638529E+38 (Double)
'
'       NaN (Single) --> -9223372036854775808 (0x8000000000000000) (Int64)
'       NaN (Single) --> 0 (0x0000000000000000) (UInt64)
'       Unable to convert NaN to Decimal.
'       NaN (Single) --> NaN (Double)
'
'       Infinity (Single) --> -9223372036854775808 (0x8000000000000000) (Int64)
'       Infinity (Single) --> 0 (0x0000000000000000) (UInt64)
'       Unable to convert Infinity to Decimal.
'       Infinity (Single) --> Infinity (Double)
'
'       -Infinity (Single) --> -9223372036854775808 (0x8000000000000000) (Int64)
'       -Infinity (Single) --> 9223372036854775808 (0x8000000000000000) (UInt64)
'       Unable to convert -Infinity to Decimal.
'       -Infinity (Single) --> -Infinity (Double)

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

Funcionalidad de punto flotante

La Single estructura y los tipos relacionados proporcionan métodos para realizar las siguientes categorías de operaciones:

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

    La Single estructura también admite un conjunto completo de operadores de comparación. Por ejemplo, puede probar la igualdad o desigualdad, o determinar si un valor es mayor o igual que otro. Si uno de los operandos es , Doubleel Single valor se convierte en un Double antes de realizar la comparación. Si uno de los operandos es un tipo entero, se convierte en un Single antes de realizar la comparación. Aunque estas son conversiones de ampliación, pueden implicar una pérdida de precisión.

    Advertencia

    Debido a las diferencias de precisión, dos Single valores que se espera que sean iguales pueden resultar desiguales, lo que afecta al resultado de la comparación. Consulte la sección Pruebas de igualdad para obtener más información sobre cómo comparar dos Single valores.

    También puede llamar a los IsNaNmétodos , IsInfinity, IsPositiveInfinityy IsNegativeInfinity para probar estos valores especiales.

  • Operaciones matemáticas. Las operaciones aritméticas comunes, como la suma, la resta, la multiplicación y la división, se implementan mediante compiladores de lenguaje y instrucciones del lenguaje intermedio común (CIL) en lugar de por Single métodos. Si el otro operando de una operación matemática es , DoubleSingle se convierte en un Double objeto antes de realizar la operación y el resultado de la operación también es un Double valor. Si el otro operando es un tipo entero, se convierte en un Single antes de realizar la operación y el resultado de la operación también es un Single valor.

    Puede realizar otras operaciones matemáticas llamando a static (Shared en Visual Basic) métodos de la System.Math clase . Estos incluyen métodos adicionales que se usan habitualmente para la aritmética (como , y ), geometry (como Math.Cos y Math.Sin) y calculus (como Math.Log).Math.SqrtMath.SignMath.Abs En todos los casos, el Single valor se convierte en .Double

    También puede manipular los bits individuales en un Single valor. El BitConverter.GetBytes(Single) método devuelve su patrón de bits en una matriz de bytes. Al pasar esa matriz de bytes al BitConverter.ToInt32 método , también puede conservar el Single patrón de bits del valor en un entero de 32 bits.

  • Redondeo. El redondeo se suele usar como técnica para reducir el impacto de las diferencias entre los valores causados por problemas de representación y precisión de punto flotante. Puede redondear un Single valor llamando al Math.Round método . Sin embargo, tenga en cuenta que el Single valor se convierte en un Double antes de llamar al método y la conversión puede implicar una pérdida de precisión.

  • Formato. Puede convertir un Single valor en su representación de cadena llamando al ToString método o mediante la característica de formato compuesto . Para obtener información sobre cómo las cadenas de formato controlan la representación de cadena de valores de punto flotante, vea los temas Cadenas de formato numérico estándar y Cadenas de formato numérico personalizado .

  • Análisis de cadenas. Puede convertir la representación de cadena de un valor de punto flotante en un Single valor llamando al Parse método o TryParse . 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.

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

    Sin embargo, la conversión de valores enteros de 32 y 64 bits puede implicar una pérdida de precisión. En la tabla siguiente se enumeran las diferencias de precisión de 32 bits, 64 bits y Double tipos:

    Tipo Precisión máxima (en dígitos decimales) Precisión interna (en dígitos decimales)
    Double 15 17
    Int32 y UInt32 10 10
    Int64 y UInt64 19 19
    Single 7 9

    El problema de precisión afecta con más frecuencia a Single los valores que se convierten en Double valores. En el ejemplo siguiente, dos valores generados por operaciones de división idénticas no son iguales, ya que uno de los valores es un valor de punto flotante de precisión sencilla que se convierte en .Double

    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
    
    let value1 = 1. / 3.
    let sValue2 = 1f / 3f
    let value2 = double sValue2
    printfn $"{value1:R} = {value2:R}: {value1.Equals value2}"
    // The example displays the following output:
    //        0.33333333333333331 = 0.3333333432674408: False
    
    Module Example
       Public Sub Main()
          Dim value1 As Double = 1/3
          Dim sValue2 As Single = 1/3
          Dim value2 As Double = CDbl(sValue2)
          Console.WriteLine("{0} = {1}: {2}", value1, value2, value1.Equals(value2))
       End Sub
    End Module
    ' The example displays the following output:
    '       0.33333333333333331 = 0.3333333432674408: False
    

Campos

Epsilon

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

MaxValue

Representa el mayor valor posible de Single. Este campo es constante.

MinValue

Representa el menor valor posible de Single. Este campo es constante.

NaN

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

NegativeInfinity

Representa infinito negativo. Este campo es constante.

PositiveInfinity

Representa infinito positivo. Este campo es constante.

Métodos

CompareTo(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.

CompareTo(Single)

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

Equals(Object)

Devuelve un valor que indica si esta instancia equivale a un objeto especificado.

Equals(Single)

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

GetHashCode()

Devuelve el código hash de esta instancia.

GetTypeCode()

Devuelve el TypeCode para el tipo de valor Single.

IsFinite(Single)

Determina si el valor especificado es limitado (cero, no normal o normal).

IsInfinity(Single)

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

IsNaN(Single)

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

IsNegative(Single)

Determina si el valor especificado es negativo.

IsNegativeInfinity(Single)

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

IsNormal(Single)

Determina si el valor especificado es normal.

IsPositiveInfinity(Single)

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

IsSubnormal(Single)

Determina si el valor especificado no es normal.

Parse(ReadOnlySpan<Char>, NumberStyles, IFormatProvider)

Convierte el intervalo de caracteres que contiene la representación de cadena de un número con el estilo y el formato específico de la referencia cultural que se hayan especificado en el número de punto flotante de precisión sencilla equivalente.

Parse(String)

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

Parse(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 sencilla equivalente.

Parse(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 sencilla equivalente.

Parse(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 sencilla equivalente.

ToString()

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

ToString(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.

ToString(String)

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

ToString(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.

TryFormat(Span<Char>, Int32, ReadOnlySpan<Char>, IFormatProvider)

Intenta dar formato al valor de la instancia del número flotante actual en el intervalo de caracteres proporcionado.

TryParse(ReadOnlySpan<Char>, NumberStyles, IFormatProvider, Single)

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

TryParse(ReadOnlySpan<Char>, Single)

Convierte la representación de cadena de un número de un intervalo de caracteres a su número de punto flotante de precisión sencilla equivalente. Un valor devuelto indica si la conversión se realizó correctamente o si se produjeron errores.

TryParse(String, NumberStyles, IFormatProvider, Single)

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 sencilla equivalente. Un valor devuelto indica si la conversión se realizó correctamente o si se produjeron errores.

TryParse(String, Single)

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

Operadores

Equality(Single, Single)

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

GreaterThan(Single, Single)

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

GreaterThanOrEqual(Single, Single)

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

Inequality(Single, Single)

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

LessThan(Single, Single)

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

LessThanOrEqual(Single, Single)

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

Implementaciones de interfaz explícitas

IComparable.CompareTo(Object)

Compara la instancia actual con otro objeto del mismo tipo y devuelve un entero que indica si la posición de la instancia actual es anterior, posterior o igual que la del otro objeto en el criterio de ordenación.

IConvertible.GetTypeCode()

Devuelve el TypeCode para esta instancia.

IConvertible.ToBoolean(IFormatProvider)

Para obtener una descripción de este miembro, vea ToBoolean(IFormatProvider).

IConvertible.ToByte(IFormatProvider)

Para obtener una descripción de este miembro, vea ToByte(IFormatProvider).

IConvertible.ToChar(IFormatProvider)

No se admite esta conversión. Cualquier intento de usar este método produce una excepción InvalidCastException.

IConvertible.ToDateTime(IFormatProvider)

No se admite esta conversión. Cualquier intento de usar este método produce una excepción InvalidCastException.

IConvertible.ToDecimal(IFormatProvider)

Para obtener una descripción de este miembro, vea ToDecimal(IFormatProvider).

IConvertible.ToDouble(IFormatProvider)

Para obtener una descripción de este miembro, vea ToDouble(IFormatProvider).

IConvertible.ToInt16(IFormatProvider)

Para obtener una descripción de este miembro, vea ToInt16(IFormatProvider).

IConvertible.ToInt32(IFormatProvider)

Para obtener una descripción de este miembro, vea ToInt32(IFormatProvider).

IConvertible.ToInt64(IFormatProvider)

Para obtener una descripción de este miembro, vea ToInt64(IFormatProvider).

IConvertible.ToSByte(IFormatProvider)

Para obtener una descripción de este miembro, vea ToSByte(IFormatProvider).

IConvertible.ToSingle(IFormatProvider)

Para obtener una descripción de este miembro, vea ToSingle(IFormatProvider).

IConvertible.ToType(Type, IFormatProvider)

Para obtener una descripción de este miembro, vea ToType(Type, IFormatProvider).

IConvertible.ToUInt16(IFormatProvider)

Para obtener una descripción de este miembro, vea ToUInt16(IFormatProvider).

IConvertible.ToUInt32(IFormatProvider)

Para obtener una descripción de este miembro, vea ToUInt32(IFormatProvider).

IConvertible.ToUInt64(IFormatProvider)

Para obtener una descripción de este miembro, vea ToUInt64(IFormatProvider).

Se aplica a

Seguridad para subprocesos

Todos los miembros de este tipo son seguros para subprocesos. Los miembros que parecen modificar el estado de la instancia devuelven realmente una nueva instancia inicializada con el nuevo valor. Al igual que con cualquier otro tipo, la lectura y escritura en una variable compartida que contiene una instancia de este tipo deben estar protegidas por un bloqueo para garantizar la seguridad de los subprocesos.

Consulte también