Single Struct

Definizione

Rappresenta un numero a virgola mobile a precisione singola.

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 : IComparable, IConvertible, IFormattable
public value class float : IComparable, IComparable<float>, IEquatable<float>, IFormattable
public struct Single : IComparable, IComparable<float>, IConvertible, IEquatable<float>, IFormattable
public struct Single : IComparable, IComparable<float>, IConvertible, IEquatable<float>, ISpanFormattable
[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
[<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 IComparable, IConvertible, IFormattable
Public Structure Single
Implements IComparable, IComparable(Of Single), IEquatable(Of Single), IFormattable
Ereditarietà
Single
Attributi
Implementazioni

Commenti

Il tipo valore rappresenta un numero a 32 bit a precisione singola con valori compresi tra Single 3,402823e38 e 3,402823e38 positivi, nonché zero positivo o negativo, , e non un numero PositiveInfinity NegativeInfinity ( NaN ). È progettato per rappresentare valori estremamente grandi (ad esempio distanze tra pianeti o pianeti) o estremamente piccoli (ad esempio la massa molecolca di una sostanza in chilogrammi) e che spesso sono imprecisi (ad esempio la distanza dalla Terra a un altro sistema solare). Il tipo è conforme a Single IEC 60559:1989 (IEEE 754) standard per l'aritmetica binaria a virgola mobile.

Questo articolo è costituito dalle sezioni seguenti:

System.Single fornisce metodi per confrontare istanze di questo tipo, per convertire il valore di un'istanza nella relativa rappresentazione di stringa e per convertire la rappresentazione di stringa di un numero in un'istanza di questo tipo. Per informazioni sul modo in cui i codici di specifica del formato controllano la rappresentazione di stringa dei tipi valore, vedere Formattazione di tipi ,Stringhe di formato numerico standarde Stringhe di formato numerico personalizzato.

Rappresentazione a virgola mobile e precisione

Il tipo di dati archivia i valori a virgola mobile e precisione singola in un formato Single binario a 32 bit, come illustrato nella tabella seguente:

Parte BITS
Significand o mantissa 0-22
Exponent 23-30
Segno (0 = positivo, 1 = negativo) 31

Proprio come le frazioni decimali non sono in grado di rappresentare con precisione alcuni valori frazionari (ad esempio 1/3 o ), le frazioni binarie non sono in grado di rappresentare Math.PI alcuni valori frazionari. Ad esempio, 2/10, rappresentato esattamente da 0,2 come frazione decimale, è rappresentato da .0011111001001100 come frazione binaria, con il modello "1100" che si ripete fino all'infinito. In questo caso, il valore a virgola mobile fornisce una rappresentazione imprecisa del numero rappresentato. L'esecuzione di operazioni matematiche aggiuntive sul valore a virgola mobile originale aumenta spesso la mancanza di precisione. Ad esempio, se si confrontano i risultati della moltiplicazione di 0,3 per 10 e dell'aggiunta di 0,3 a 0,3 nove volte, l'addizione produce il risultato meno preciso, perché comporta otto operazioni in più rispetto alla moltiplicazione. Si noti che questa disparità è evidente solo se si visualizzano i due valori usando la stringa di formato Single numerico standard"R", che, se necessario, visualizza tutte le 9 cifre di precisione supportate dal 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
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

Poiché alcuni numeri non possono essere rappresentati esattamente come valori binari frazionari, i numeri a virgola mobile possono solo approssimare numeri reali.

Tutti i numeri a virgola mobile hanno un numero limitato di cifre significative, che determina anche la precisione con cui un valore a virgola mobile si avvicina a un numero reale. Un Single valore ha fino a 7 cifre decimali di precisione, anche se un massimo di 9 cifre viene mantenuto internamente. Ciò significa che alcune operazioni a virgola mobile potrebbero non avere la precisione per modificare un valore a virgola mobile. L'esempio seguente definisce un valore a virgola mobile a precisione singola di grandi dimensioni e quindi aggiunge il prodotto di e un Single.Epsilon quadrilione. Tuttavia, il prodotto è troppo piccolo per modificare il valore a virgola mobile originale. La cifra meno significativa è il millesimo, mentre la cifra più significativa nel prodotto è 10-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
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 precisione limitata di un numero a virgola mobile ha diverse conseguenze:

  • Due numeri a virgola mobile apparentemente uguali per una particolare precisione potrebbero non risultare uguali, in quanto le relative cifre meno significative sono diverse. Nell'esempio seguente viene sommata una serie di numeri e il totale viene confrontato con il totale previsto. Anche se i due valori sembrano essere uguali, una chiamata al metodo Equals indica che non lo sono.

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

    Se si modificano gli elementi di formato nell'istruzione da e verso e per visualizzare tutte le cifre significative dei due valori, è chiaro che i due valori non sono uguali a causa di una perdita di precisione durante le operazioni di Console.WriteLine(String, Object, Object) {0} {1} {0:R} {1:R} Single addizione. In questo caso, il problema può essere risolto chiamando il metodo per arrotondare i valori alla precisione desiderata Math.Round(Double, Int32) prima di eseguire il Single confronto.

  • Un'operazione matematica o di confronto che usa un numero a virgola mobile potrebbe non produrre lo stesso risultato se viene usato un numero decimale, perché il numero a virgola mobile binario potrebbe non essere uguale al numero decimale. Un esempio precedente ha illustrato questo risultato visualizzando il risultato della moltiplicazione di 0,3 per 10 e dell'aggiunta di 0,3 a 0,3 nove volte.

    Quando l'accuratezza nelle operazioni numeriche con valori frazionari è importante, usare il Decimal tipo anziché il tipo Single . Quando l'accuratezza nelle operazioni numeriche con valori integrali oltre l'intervallo dei tipi o è Int64 UInt64 importante, usare il BigInteger tipo .

  • Un valore potrebbe non essere round trip se è coinvolto un numero a virgola mobile. Un valore viene detto round trip se un'operazione converte un numero a virgola mobile originale in un altro formato, un'operazione inversa trasforma il form convertito in un numero a virgola mobile e il numero a virgola mobile finale è uguale al numero a virgola mobile originale. Il round trip potrebbe non riuscire perché una o più cifre meno significative vengono perse o modificate in una conversione. Nell'esempio seguente tre Single valori vengono convertiti in stringhe e salvati in un file. Come illustrato nell'output, anche se i valori sembrano identici, i valori ripristinati non sono uguali ai valori originali.

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

    In questo caso, è possibile eseguire correttamente il round trip dei valori usando la stringa di formato numerico standard "G9" per mantenere la precisione completa dei valori, come illustrato Single nell'esempio seguente.

    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
    
    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 i valori hanno una precisione minore rispetto ai Double valori. Un valore convertito in un oggetto apparentemente equivalente spesso non è uguale al valore Single a causa di differenze di Double Double precisione. Nell'esempio seguente il risultato di operazioni di divisione identiche viene assegnato a un Double valore e a un valore Single . Dopo il cast del valore a , un confronto tra i due valori mostra Single Double che non sono uguali.

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

    Per evitare questo problema, usare il tipo di dati al posto del tipo di dati oppure usare il metodo in modo che entrambi i valori Double Single hanno la stessa Round precisione.

Test dell'uguaglianza

Per essere considerati uguali, due Single valori devono rappresentare valori identici. Tuttavia, a causa delle differenze di precisione tra i valori o a causa di una perdita di precisione di uno o di entrambi i valori, i valori a virgola mobile che si prevede siano identici spesso non sono uguali a causa delle differenze nelle cifre meno significative. Di conseguenza, le chiamate al metodo per determinare se due valori sono uguali o chiamate al metodo per determinare la relazione tra due valori, generando spesso Equals CompareTo risultati Single imprevisti. Questo è evidente nell'esempio seguente, in cui due valori apparentemente uguali non sono uguali, perché il primo valore ha 7 cifre di precisione, mentre il secondo valore Single ha 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
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

I valori calcolati che seguono percorsi di codice diversi e che vengono manipolati in modi diversi spesso si rivelano disuguali. Nell'esempio seguente un valore viene quadrato e quindi viene calcolata la radice quadrata Single per ripristinare il valore originale. Un secondo viene moltiplicato per 3,51 e quadrato prima che la radice quadrata del risultato venga divisa Single per 3,51 per ripristinare il valore originale. Anche se i due valori sembrano identici, una chiamata al metodo indica che Equals(Single) non sono uguali. L'uso della stringa di formato standard "G9" per restituire una stringa di risultato che visualizza tutte le cifre significative di ogni valore indica che il secondo valore è 0000000000001 minore Single del primo.

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

Nei casi in cui è probabile che una perdita di precisione influisca sul risultato di un confronto, è possibile usare le tecniche seguenti invece di chiamare il Equals metodo o CompareTo :

  • Chiamare il Math.Round metodo per assicurarsi che entrambi i valori hanno la stessa precisione. L'esempio seguente modifica un esempio precedente per usare questo approccio in modo che due valori frazionari siano equivalenti.

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

    Il problema della precisione si applica ancora all'arrotondamento dei valori del punto medio. Per altre informazioni, vedere il metodo Math.Round(Double, Int32, MidpointRounding).

  • Verificare l'uguaglianza approssimativa anziché l'uguaglianza. Questa tecnica richiede di definire un importo assoluto in base al quale i due valori possono differire ma essere comunque uguali oppure di definire una quantità relativa in base alla quale il valore più piccolo può divergere dal valore più grande.

    Avviso

    Single.Epsilon viene talvolta usato come misura assoluta della distanza tra due Single valori durante il test dell'uguaglianza. Misura tuttavia il valore più piccolo possibile che può essere aggiunto o sottratto Single.Epsilon da un oggetto il cui valore è Single zero. Per la maggior parte dei valori positivi e Single negativi, il valore di Single.Epsilon è troppo piccolo per essere rilevato. Pertanto, ad eccezione dei valori pari a zero, non è consigliabile usarlo nei test per verificarne l'uguaglianza.

    Nell'esempio seguente viene utilizzato il secondo approccio per definire un IsApproximatelyEqual metodo che verifica la differenza relativa tra due valori. Contrasta anche il risultato delle chiamate al IsApproximatelyEqual metodo e al metodo Equals(Single) .

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

Valori ed eccezioni a virgola mobile

Le operazioni con valori a virgola mobile non generano eccezioni, a differenza delle operazioni con tipi integrali, che generano eccezioni in caso di operazioni non consentite, ad esempio la divisione per zero o l'overflow. In queste situazioni, invece, il risultato di un'operazione a virgola mobile è zero, infinito positivo, infinito negativo o non un numero (NaN):

  • Se il risultato di un'operazione a virgola mobile è troppo piccolo per il formato di destinazione, il risultato è zero. Ciò può verificarsi quando vengono moltiplicati due numeri a virgola mobile molto piccoli, come illustrato nell'esempio seguente.

    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
    
    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
    
  • Se la grandezza del risultato di un'operazione a virgola mobile supera l'intervallo del formato di destinazione, il risultato dell'operazione è o , come appropriato per il segno PositiveInfinity NegativeInfinity del risultato. Il risultato di un'operazione che causa un overflow è e il risultato di un'operazione che causa un overflow è Single.MaxValue PositiveInfinity , come illustrato Single.MinValue NegativeInfinity nell'esempio seguente.

    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
    
    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 deriva anche da una divisione per zero con un dividendo positivo e da NegativeInfinity una divisione per zero con un dividendo negativo.

  • Se un'operazione a virgola mobile non è valida, il risultato dell'operazione è NaN . Ad esempio, NaN i risultati delle operazioni seguenti:

    • Divisione per zero con dividendo pari a zero. Si noti che altri casi di divisione per zero comportano PositiveInfinity o NegativeInfinity .

    • Qualsiasi operazione a virgola mobile con input non valido. Ad esempio, il tentativo di trovare la radice quadrata di un valore negativo restituisce NaN .

    • Qualsiasi operazione con un argomento il cui valore è Single.NaN .

Conversioni di tipi e struttura Single

La Single struttura non definisce alcun operatore di conversione esplicito o implicito. Le conversioni vengono invece implementate dal compilatore.

La tabella seguente elenca le possibili conversioni di un valore degli altri tipi numerici primitivi in un valore . Indica anche se la conversione è più ampia o più stretta e se il risultato può avere una precisione inferiore rispetto al valore Single Single originale.

Conversione da Widening/narrowing Possibile perdita di precisione
Byte Widening No
Decimal Widening

Si noti che C# richiede un operatore cast.
Sì. Decimal supporta 29 cifre decimali di precisione. Single supporta 9.
Double Narrowing; I valori non compreso nell'intervallo vengono convertiti in Double.NegativeInfinity o Double.PositiveInfinity . Sì. Double supporta 17 cifre decimali di precisione. Single supporta 9.
Int16 Widening No
Int32 Widening Sì. Int32 supporta 10 cifre decimali di precisione. Single supporta 9.
Int64 Widening Sì. Int64 supporta 19 cifre decimali di precisione. Single supporta 9.
SByte Widening No
UInt16 Widening No
UInt32 Widening Sì. UInt32 supporta 10 cifre decimali di precisione. Single supporta 9.
UInt64 Widening Sì. Int64 supporta 20 cifre decimali di precisione. Single supporta 9.

Nell'esempio seguente il valore minimo o massimo di altri tipi numerici primitivi viene convertito in Single un valore .

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

Inoltre, i Double valori , e vengono convertiti Double.NaN Double.PositiveInfinity Double.NegativeInfinity rispettivamente in , e Single.NaN Single.PositiveInfinity Single.NegativeInfinity .

Si noti che la conversione del valore di alcuni tipi numerici in un Single valore può comportare una perdita di precisione. Come illustrato nell'esempio, è possibile una perdita di precisione durante la conversione dei valori , Decimal , , , e in valori Double Int32 Int64 UInt32 UInt64 Single .

La conversione di un Single valore in è una Double conversione verso un tipo di dati più grande. La conversione può comportare una perdita di precisione se Double il tipo non dispone di una rappresentazione precisa per il Single valore.

La conversione di un valore in un valore di qualsiasi tipo di dati numeric primitivo diverso da è una conversione verso un tipo di dati più ristretto e richiede un operatore cast (in C#) o un metodo di Single Double conversione (in Visual Basic). I valori non compreso nell'intervallo del tipo di dati di destinazione, definiti dalle proprietà e del tipo di destinazione, si comportano MinValue come illustrato nella tabella MaxValue seguente.

Tipo di destinazione Risultato
Qualsiasi tipo integrale Eccezione OverflowException se la conversione si verifica in un contesto controllato.

Se la conversione viene eseguita in un contesto non controllato (impostazione predefinita in C#), l'operazione di conversione ha esito positivo, ma il valore è in overflow.
Decimal OverflowExceptionUn'eccezione,

Inoltre, , e generano un'eccezione per le conversioni in integer in un contesto controllato, ma questi valori causano un overflow quando vengono convertiti Single.NaN Single.PositiveInfinity in numeri Single.NegativeInfinity OverflowException interi in un contesto non verificato. Per le conversioni in Decimal , generano sempre un'eccezione OverflowException . Per le conversioni Double in , vengono convertite Double.NaN Double.PositiveInfinity rispettivamente in , e Double.NegativeInfinity .

Si noti che una perdita di precisione può derivare dalla conversione di Single un valore in un altro tipo numerico. Nel caso della conversione di valori non integrali, come illustrato nell'output dell'esempio, il componente frazionario viene perso quando il valore viene arrotondato (come in Visual Basic) o troncato Single Single (come in C#). Per le conversioni Decimal in valori , il valore potrebbe non avere una Single rappresentazione precisa nel tipo di dati di destinazione.

Nell'esempio seguente viene convertito un numero Single di valori in diversi altri tipi numerici. Le conversioni si verificano in un contesto controllato in Visual Basic (impostazione predefinita) e in C# (a causa della parola chiave checked). L'output dell'esempio mostra il risultato per le conversioni in un contesto verificato e non verificato. È possibile eseguire conversioni in un contesto non controllato in Visual Basic compilando con l'opzione del compilatore e in C# impostando come /removeintchecks+ commento checked l'istruzione .

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

Per altre informazioni sulla conversione di tipi numerici, vedere Conversione dei tipi nelle tabelle .NET Framework e conversione dei tipi.

Funzionalità a virgola mobile

La Single struttura e i tipi correlati forniscono metodi per eseguire le categorie di operazioni seguenti:

  • Confronto dei valori. È possibile chiamare il Equals metodo per determinare se due valori sono uguali o il metodo per Single CompareTo determinare la relazione tra due valori.

    La Single struttura supporta anche un set completo di operatori di confronto. Ad esempio, è possibile verificare l'uguaglianza o la disuguaglianza o determinare se un valore è maggiore o uguale a un altro valore. Se uno degli operandi è , il valore viene Double convertito in prima di eseguire il Single Double confronto. Se uno degli operandi è un tipo integrale, viene convertito in prima Single di eseguire il confronto. Anche se si tratta di conversioni verso un tipo di dati più grande, possono comportare una perdita di precisione.

    Avviso

    A causa delle differenze di precisione, due valori che si prevede siano uguali possono risultare diversi, con effetti sul Single risultato del confronto. Per altre informazioni sul confronto di due valori, vedere la sezione Test per l'uguaglianza. Single

    È anche possibile chiamare i IsNaN metodi , , e per IsInfinity IsPositiveInfinity IsNegativeInfinity testare questi valori speciali.

  • Operazioni matematiche. Le operazioni aritmetiche comuni, ad esempio addizione, sottrazione, moltiplicazione e divisione, vengono implementate dai compilatori di linguaggio e dalle istruzioni Common Intermediate Language (CIL) anziché dai Single metodi. Se l'altro operando in un'operazione matematica è , viene convertito in prima di eseguire l'operazione e anche il risultato dell'operazione Double Single è un valore Double Double . Se l'altro operando è un tipo integrale, viene convertito in un oggetto prima di eseguire l'operazione e anche il risultato dell'operazione Single è un Single valore.

    È possibile eseguire altre operazioni matematiche chiamando static i metodi ( Shared Visual Basic) nella classe System.Math . Questi includono metodi aggiuntivi comunemente usati per l'aritmetica (ad esempio , e ), geometry (ad esempio e ) e Math.Abs Math.Sign Math.Sqrt Math.Cos Math.Sin calculus (ad esempio Math.Log ). In tutti i casi, Single il valore viene convertito in Double .

    È anche possibile modificare i singoli bit in un Single valore. Il BitConverter.GetBytes(Single) metodo restituisce il modello di bit in una matrice di byte. Passando tale matrice di byte al metodo , è anche possibile mantenere il modello di bit del valore BitConverter.ToInt32 in un intero a Single 32 bit.

  • Arrotondamento di. L'arrotondamento viene spesso usato come tecnica per ridurre l'impatto delle differenze tra i valori causati da problemi di rappresentazione a virgola mobile e precisione. È possibile arrotondare Single un valore chiamando il metodo Math.Round . Si noti tuttavia che il valore viene convertito in prima della chiamata al metodo e la conversione può Single comportare una perdita di Double precisione.

  • Formattazione di. È possibile convertire un Single valore nella relativa rappresentazione di stringa chiamando il ToString metodo o usando la funzionalità di formattazione composita. Per informazioni sul modo in cui le stringhe di formato controllano la rappresentazione di stringa dei valori a virgola mobile, vedere gli argomenti Stringhe di formato numerico standard e Stringhe di formato numerico personalizzato.

  • Analisi di stringhe. È possibile convertire la rappresentazione di stringa di un valore a virgola mobile in un Single valore chiamando il metodo o Parse TryParse . Se l'operazione di analisi non riesce, Parse il metodo genera un'eccezione, mentre il TryParse metodo restituisce false .

  • Conversione dei tipi. La Single struttura fornisce un'implementazione esplicita dell'interfaccia per l'interfaccia , che supporta la conversione tra due tipi di dati .NET Framework IConvertible standard. I compilatori di linguaggio supportano anche la conversione implicita di valori per tutti gli altri tipi numerici standard, ad eccezione della conversione di Double in Single valori . La conversione di un valore di qualsiasi tipo numerico standard diverso da in un tipo è una conversione verso un tipo di dati più grande e non richiede l'uso di un operatore di cast o di Double Single un metodo di conversione.

    Tuttavia, la conversione di valori integer a 32 bit e a 64 bit può comportare una perdita di precisione. Nella tabella seguente sono elencate le differenze di precisione per i tipi a 32 bit, a 64 bit e Double :

    Tipo Precisione massima (in cifre decimali) Precisione interna (in cifre decimali)
    Double 15 17
    Int32 e UInt32 10 10
    Int64 e UInt64 19 19
    Single 7 9

    Il problema della precisione influisce più frequentemente Single sui valori convertiti in Double valori. Nell'esempio seguente due valori prodotti da operazioni di divisione identiche non sono uguali, perché uno dei valori è un valore a virgola mobile a precisione singola convertito in 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
    
    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
    

Campi

Epsilon

Rappresenta il valore Single positivo più piccolo maggiore di zero. Questo campo è costante.

MaxValue

Rappresenta il valore massimo possibile di Single. Questo campo è costante.

MinValue

Rappresenta il valore più piccolo possibile di Single. Questo campo è costante.

NaN

Rappresenta un valore non numerico (NaN). Questo campo è costante.

NegativeInfinity

Rappresenta l'infinito negativo. Questo campo è costante.

PositiveInfinity

Rappresenta l'infinito positivo. Questo campo è costante.

Metodi

CompareTo(Object)

Confronta questa istanza con un oggetto specificato e restituisce un intero che indica se il valore di questa istanza è minore, uguale o maggiore rispetto al valore dell'oggetto specificato.

CompareTo(Single)

Confronta questa istanza con un numero a virgola mobile a precisione singola specificato e restituisce un intero che indica se il valore di questa istanza è minore, uguale o maggiore del valore del numero a virgola mobile a precisione singola specificato.

Equals(Object)

Restituisce un valore che indica se questa istanza è uguale a un oggetto specificato.

Equals(Single)

Restituisce un valore che indica se l'istanza e un oggetto Single specificato rappresentano lo stesso valore.

GetHashCode()

Restituisce il codice hash per l'istanza.

GetTypeCode()

Restituisce l'oggetto TypeCode del tipo di valore Single.

IsFinite(Single)

Determina se il valore specificato è finito (zero, subnormale o normale).

IsInfinity(Single)

Restituisce un valore che indica se il numero specificato restituisce l'infinito negativo o positivo.

IsNaN(Single)

Restituisce un valore che indica se il valore specificato non è un numero (NaN).

IsNegative(Single)

Determina se il valore specificato è negativo.

IsNegativeInfinity(Single)

Restituisce un valore che indica se il numero specificato restituisce l'infinito negativo.

IsNormal(Single)

Determina se il valore specificato è normale.

IsPositiveInfinity(Single)

Restituisce un valore che indica se il numero specificato restituisce l'infinito positivo.

IsSubnormal(Single)

Determina se il valore specificato è subnormale.

Parse(ReadOnlySpan<Char>, NumberStyles, IFormatProvider)

Converte un intervallo di caratteri che contiene la rappresentazione stringa di un numero in uno stile specificato e in un formato specifico delle impostazioni cultura nel numero a virgola mobile a precisione singola equivalente.

Parse(String)

Converte la rappresentazione di stringa di un numero nel numero a virgola mobile a precisione singola equivalente.

Parse(String, IFormatProvider)

Converte la rappresentazione di stringa di un numero in un determinato formato specifico delle impostazioni cultura nel numero a virgola mobile a precisione singola equivalente.

Parse(String, NumberStyles)

Converte la rappresentazione di stringa di un numero in uno stile specificato nel rispettivo numero a virgola mobile a precisione singola equivalente.

Parse(String, NumberStyles, IFormatProvider)

Converte la rappresentazione di stringa di un numero in uno stile specificato e in un formato specifico delle impostazioni cultura nel numero a virgola mobile a precisione singola equivalente.

ToString()

Converte il valore numerico dell'istanza nella rappresentazione di stringa equivalente.

ToString(IFormatProvider)

Converte il valore numerico di questa istanza nella rappresentazione di stringa equivalente usando le informazioni di formato specifiche delle impostazioni cultura.

ToString(String)

Converte il valore numerico di questa istanza nell'equivalente rappresentazione di stringa usando il formato specificato.

ToString(String, IFormatProvider)

Converte il valore numerico dell'istanza nella rappresentazione di stringa equivalente usando il formato specificato e le informazioni di formattazione specifiche delle impostazioni cultura.

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

Prova a formattare il valore dell'istanza del numero float corrente nell'intervallo di caratteri specificato.

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

Converte la rappresentazione intervallo di un numero in uno stile specificato e in un formato specifico delle impostazioni cultura nel numero a virgola mobile a precisione singola equivalente. Un valore restituito indica se la conversione è riuscita o meno.

TryParse(ReadOnlySpan<Char>, Single)

Converte la rappresentazione stringa di un numero in un intervallo di caratteri nel numero a virgola mobile a precisione singola equivalente. Un valore restituito indica se la conversione è riuscita o meno.

TryParse(String, NumberStyles, IFormatProvider, Single)

Converte la rappresentazione di stringa di un numero in uno stile specificato e in un formato specifico delle impostazioni cultura nel numero a virgola mobile a precisione singola equivalente. Un valore restituito indica se la conversione è riuscita o meno.

TryParse(String, Single)

Converte la rappresentazione di stringa di un numero nel numero a virgola mobile a precisione singola equivalente. Un valore restituito indica se la conversione è riuscita o meno.

Operatori

Equality(Single, Single)

Restituisce un valore che indica se due valori Single specificati sono uguali.

GreaterThan(Single, Single)

Restituisce un valore che indica se un valore Singlespecificato è maggiore di un altro valore Single specificato.

GreaterThanOrEqual(Single, Single)

Restituisce un valore che indica se un valore Single specificato è maggiore o uguale a un altro valore Single specificato.

Inequality(Single, Single)

Restituisce un valore che indica se due valori Single specificati non sono uguali.

LessThan(Single, Single)

Restituisce un valore che indica se il valore Single specificato è minore o uguale a un altro valore Single specificato.

LessThanOrEqual(Single, Single)

Restituisce un valore che indica se un valore Single specificato è minore o uguale a un altro valore Single specificato.

Implementazioni dell'interfaccia esplicita

IComparable.CompareTo(Object)

Confronta l'istanza corrente con un altro oggetto dello stesso tipo e restituisce un intero che indica se l'istanza corrente precede, segue o si trova nella stessa posizione dell'altro oggetto all'interno dell'ordinamento.

IConvertible.GetTypeCode()

Restituisce l'oggetto TypeCode per questa istanza.

IConvertible.ToBoolean(IFormatProvider)

Per una descrizione di questo membro, vedere ToBoolean(IFormatProvider).

IConvertible.ToByte(IFormatProvider)

Per una descrizione di questo membro, vedere ToByte(IFormatProvider).

IConvertible.ToChar(IFormatProvider)

Questa conversione non è supportata. Il tentativo di usare questo metodo genera un'eccezione InvalidCastException.

IConvertible.ToDateTime(IFormatProvider)

Questa conversione non è supportata. Il tentativo di usare questo metodo genera un'eccezione InvalidCastException.

IConvertible.ToDecimal(IFormatProvider)

Per una descrizione di questo membro, vedere ToDecimal(IFormatProvider).

IConvertible.ToDouble(IFormatProvider)

Per una descrizione di questo membro, vedere ToDouble(IFormatProvider).

IConvertible.ToInt16(IFormatProvider)

Per una descrizione di questo membro, vedere ToInt16(IFormatProvider).

IConvertible.ToInt32(IFormatProvider)

Per una descrizione di questo membro, vedere ToInt32(IFormatProvider).

IConvertible.ToInt64(IFormatProvider)

Per una descrizione di questo membro, vedere ToInt64(IFormatProvider).

IConvertible.ToSByte(IFormatProvider)

Per una descrizione di questo membro, vedere ToSByte(IFormatProvider).

IConvertible.ToSingle(IFormatProvider)

Per una descrizione di questo membro, vedere ToSingle(IFormatProvider).

IConvertible.ToType(Type, IFormatProvider)

Per una descrizione di questo membro, vedere ToType(Type, IFormatProvider).

IConvertible.ToUInt16(IFormatProvider)

Per una descrizione di questo membro, vedere ToUInt16(IFormatProvider).

IConvertible.ToUInt32(IFormatProvider)

Per una descrizione di questo membro, vedere ToUInt32(IFormatProvider).

IConvertible.ToUInt64(IFormatProvider)

Per una descrizione di questo membro, vedere ToUInt64(IFormatProvider).

Si applica a

Thread safety

Tutti i membri di questo tipo sono thread-safe. I membri che sembrano modificare lo stato dell'istanza restituiscono effettivamente una nuova istanza inizializzata con il nuovo valore. Come per qualsiasi altro tipo, la lettura e la scrittura in una variabile condivisa che contiene un'istanza di questo tipo devono essere protette da un blocco per garantire la thread safety.

Vedi anche