Single Struktura

Definicja

Reprezentuje liczbę zmiennoprzecinkową o pojedynczej precyzji.

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
Dziedziczenie
Single
Atrybuty
Implementuje

Uwagi

Typ wartości reprezentuje liczbę 32-bitową o pojedynczej precyzji z wartościami od Single ujemnymi 3,402823e38 do dodatnimi 3,402823e38, a także zerem dodatnim lub ujemnym, PositiveInfinity , , a nie liczbą ( NegativeInfinity NaN ). Jest ona przeznaczona do reprezentowania bardzo dużych wartości (takich jak odległości między planetami lub molekularnymi) lub bardzo małych (takich jak masa molekularna osadu w molekularnym) i które często są niedokładne (na przykład odległość od Ziemi do innego układu słonecznego). Typ Single jest zgodny ze standardem IEC 60559:1989 (IEEE 754) dla binarnej arytmetyki zmiennoprzecinków.

Ten artykuł składa się z następujących sekcji:

System.Single Metoda udostępnia metody porównywania wystąpień tego typu, konwertowania wartości wystąpienia na jego reprezentację w postaci ciągu i konwertowania ciągu reprezentacji liczby na wystąpienie tego typu. Aby uzyskać informacje o tym, jak kody specyfikacji formatu kontrolują reprezentację ciągów typów wartości, zobacz Typy formatowania, Standardoweciągi formatu liczbowego i Niestandardowe ciągi formatu liczbowego.

Reprezentacja liczb zmiennoprzecinkowych i precyzja

Typ danych przechowuje wartości zmiennoprzecinkowe o pojedynczej precyzji w Single 32-bitowym formacie binarnym, jak pokazano w poniższej tabeli:

Część Bity
Significand lub mantissa 0-22
Wykładnik 23-30
Znak (0 = dodatni, 1 = ujemny) 31

Tak jak ułamki dziesiętne nie mogą precyzyjnie reprezentować niektórych wartości ułamkowych (takich jak 1/3 lub ), ułamki binarne nie mogą reprezentować niektórych Math.PI wartości ułamkowych. Na przykład 2/10, który jest reprezentowany dokładnie przez .2 jako ułamek dziesiętny, jest reprezentowany przez .0011111001001100 jako ułamek binarny, ze wzorcem "1100" powtarzanym do nieskończoności. W tym przypadku wartość zmiennoprzecinkowa zapewnia niedokładną reprezentację liczby, która reprezentuje. Wykonywanie dodatkowych operacji matematycznych na oryginalnej wartości zmiennoprzecinkowej często zwiększa jej brak precyzji. Jeśli na przykład porównasz wyniki mnożenia wartości 0,3 przez 10 i dodawania 0,3 do 0,3 dziewięciokrotnie, zobaczysz, że dodanie daje mniej precyzyjny wynik, ponieważ obejmuje osiem operacji więcej niż mnożenie. Należy pamiętać, że ta rozbieżność jest widoczna tylko wtedy, gdy dwie wartości są wyświetlane przy użyciu ciągu standardowego formatu liczbowego "R", który w razie potrzeby wyświetla wszystkie 9 cyfr dokładności obsługiwanych przez Single Single typ.

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

Ponieważ niektóre liczby nie mogą być reprezentowane dokładnie jako ułamkowe wartości binarne, liczby zmiennoprzecinkcyjne mogą być przybliżone tylko liczby rzeczywiste.

Wszystkie liczby zmiennoprzecinkowe mają ograniczoną liczbę cyfr znaczących, co określa również, jak dokładnie wartość zmiennoprzecinkowa przybliżona jest liczba rzeczywista. Wartość ma do 7 cyfr dziesiętnych precyzji, ale maksymalnie 9 cyfr jest Single utrzymywana wewnętrznie. Oznacza to, że niektóre operacje zmiennoprzecinkowe mogą nie mieć precyzji, aby zmienić wartość zmiennoprzecinkową. W poniższym przykładzie zdefiniowano dużą wartość zmiennoprzecinkową o pojedynczej precyzji, a następnie dodano do niego i produkt oraz Single.Epsilon jeden czworokąt. Jednak produkt jest zbyt mały, aby zmodyfikować oryginalną wartość zmiennoprzecinkową. Najmniej znacząca cyfra to tysięczna cyfra, a najbardziej znacząca cyfra w produkcie to10–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

Ograniczona precyzja liczby zmiennoprzecinkowej ma kilka konsekwencji:

  • Dwie liczby zmiennoprzecinkowe, które wydają się równe dla określonej precyzji, mogą nie być porównywane jako równe, ponieważ ich najmniej znaczące cyfry są różne. W poniższym przykładzie seria liczb jest dodawana razem, a ich suma jest porównywana z ich oczekiwaną sumą. Mimo że te dwie wartości wydają się być takie same, wywołanie metody Equals wskazuje, że nie są.

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

    Jeśli zmienisz elementy formatu w instrukcji z i na i w celu wyświetlenia wszystkich znaczących cyfr tych dwóch wartości, jest jasne, że te dwie wartości są nierówne z powodu utraty dokładności podczas operacji Console.WriteLine(String, Object, Object) {0} {1} {0:R} {1:R} Single dodatku. W takim przypadku problem można rozwiązać, wywołując metodę w celu zaokrąglania wartości do żądanej dokładności Math.Round(Double, Int32) Single przed wykonaniem porównania.

  • Operacja matematyczna lub porównawcza, która używa liczby zmiennoprzecinkowej, może nie przynieść tego samego wyniku, jeśli jest używana liczba dziesiętna, ponieważ binarna liczba zmiennoprzecinkowa może nie być równa liczbie dziesiętnej. W poprzednim przykładzie pokazano to, wyświetlając wynik pomnożenia wartości 0,3 przez 10 i dodania 0,3 do 0,3 dziewięciokrotnie.

    Gdy dokładność w operacjach liczbowych z wartościami ułamkowym jest ważna, należy użyć Decimal typu zamiast Single typu . Gdy dokładność w operacjach liczbowych z wartościami całkowitoliczbowym spoza zakresu typów lub jest Int64 UInt64 ważna, użyj BigInteger typu .

  • Jeśli liczba zmiennoprzecinkowa jest w tym uczestniczyć, wartość może nie być w obie strony. Wartość jest mówiona do rundy, jeśli operacja konwertuje oryginalną liczbę zmiennoprzecinkową na inną formę, odwrotna operacja przekształca przekonwertowany formularz z powrotem na liczbę zmiennoprzecinkową, a końcowa liczba zmiennoprzecinkowa jest równa oryginalnej liczbie zmiennoprzecinkowej. Runda może się nie powieść, ponieważ co najmniej jedna cyfra znacząca jest tracona lub zmieniona w konwersji. W poniższym przykładzie trzy Single wartości są konwertowane na ciągi i zapisywane w pliku. Jak widać w danych wyjściowych, mimo że wartości wydają się identyczne, przywrócone wartości nie są równe oryginalnym wartościom.

    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
    

    W takim przypadku wartości można pomyślnie zaokrąglić przy użyciu ciągu standardowego formatu liczbowego "G9", aby zachować pełną dokładność wartości, jak pokazano w Single poniższym przykładzie.

    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 Wartości mają mniejszą precyzję niż Double wartości. Wartość, która jest konwertowana na pozornie równoważny, często nie jest równa wartości ze względu Single Double na różnice w Double dokładności. W poniższym przykładzie wynik identycznych operacji dzielenia jest przypisywany do Double wartości i Single wartości. Po rzutowania wartości na wartość porównanie dwóch wartości pokazuje, że Single Double są nierówne.

    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
    

    Aby uniknąć tego problemu, użyj typu danych w miejsce typu danych lub użyj metody , aby obie wartości były takie Double Single Round same.

Testowanie pod kątem równości

Aby można je było uznać za równe, Single dwie wartości muszą reprezentować identyczne wartości. Jednak ze względu na różnice w dokładności między wartościami lub z powodu utraty dokładności przez jedną lub obie wartości wartości zmiennoprzecinkowe, które powinny być identyczne, często okazuje się nierówne ze względu na różnice w najmniej znaczących cyfrach. W związku z tym wywołania metody w celu ustalenia, czy dwie wartości są równe, lub wywołania metody w celu określenia relacji między dwiema wartościami, często Equals CompareTo dają Single nieoczekiwane wyniki. Jest to oczywiste w poniższym przykładzie, gdzie dwie wyraźnie równe wartości okazuje się nierówne, ponieważ pierwsza wartość ma 7 cyfr dokładności, a druga wartość Single ma 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

Obliczone wartości, które podążają różnymi ścieżkami kodu i są manipulowane na różne sposoby, często okazują się nierówne. W poniższym przykładzie jedna wartość jest kwadratem, a następnie pierwiastek kwadratowy jest obliczany w Single celu przywrócenia oryginalnej wartości. Sekunda jest mnożona przez 3,51 i do kwadratu przed pierwiastek kwadratowy wyniku jest dzielona przez Single 3,51, aby przywrócić oryginalną wartość. Chociaż te dwie wartości wydają się identyczne, wywołanie metody wskazuje, że Equals(Single) nie są równe. Użycie ciągu formatu standardowego "G9" w celu zwrócenia ciągu wynikowego, który wyświetla wszystkie cyfry znaczące każdej wartości, pokazuje, że druga wartość jest 0000000000001 mniejsza niż Single pierwsza.

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

W przypadkach, gdy utrata dokładności może mieć wpływ na wynik porównania, można użyć następujących technik zamiast wywoływania Equals metody CompareTo lub :

  • Wywołaj Math.Round metodę , aby upewnić się, że obie wartości mają taką samą precyzję. W poniższym przykładzie zmodyfikuje się poprzedni przykład, aby użyć tego podejścia, tak aby dwie wartości ułamkowe były równoważne.

    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
    

    Problem dokładności nadal dotyczy zaokrąglania wartości punktu środkowego. Aby uzyskać więcej informacji, zobacz Math.Round(Double, Int32, MidpointRounding) metodę .

  • Przetestuj przybliżoną równość zamiast równości. Ta technika wymaga zdefiniowania wartości bezwzględnej, o którą te dwie wartości mogą się różnić, ale nadal być równe, lub zdefiniowania względnej ilości, o którą mniejsza wartość może różnić się od większej wartości.

    Ostrzeżenie

    Single.Epsilon Jest czasami używany jako bezwzględna miara odległości między dwiema Single wartościami podczas testowania równości. Jednak miara mierzy najmniejszą możliwą wartość, która może zostać dodana do lub odjęta Single.Epsilon od, której Single wartość wynosi zero. W przypadku większości wartości dodatnich i Single ujemnych wartość jest Single.Epsilon zbyt mała, aby można było jej wykryć. W związku z tym, z wyjątkiem wartości, które są równe zero, nie zaleca się ich użycia w testach równości.

    W poniższym przykładzie użyto drugiego podejścia do zdefiniowania metody, która IsApproximatelyEqual testuje względną różnicę między dwiema wartościami. Ponadto kontrastuje wynik wywołań metody IsApproximatelyEqual i Equals(Single) metody .

    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
    

Wartości zmiennoprzecinkowe i wyjątki

Operacje z wartościami zmiennoprzecinjącymi nie zwracają wyjątków, w przeciwieństwie do operacji z typami całkowitoprzecinjącymi, które zwracają wyjątki w przypadkach niedozwolonych operacji, takich jak dzielenie przez zero lub przepełnienie. Zamiast tego w takich sytuacjach wynikiem operacji zmiennoprzecinkowej jest zero, nieskończoność dodatnia, nieskończoność ujemna lub nie liczba (NaN):

  • Jeśli wynik operacji zmiennoprzecinkowej jest zbyt mały dla formatu docelowego, wynik wynosi zero. Taka możliwość może wystąpić, gdy zostaną pomnożone dwie bardzo małe liczby zmiennoprzecinkowe, jak pokazano w poniższym przykładzie.

    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
    
  • Jeśli wielkość wyniku operacji zmiennoprzecinkowej przekracza zakres formatu docelowego, wynikiem operacji jest lub , odpowiednio dla znaku PositiveInfinity NegativeInfinity wyniku. Wynikiem operacji, która przepełnia, jest , a wynikiem operacji, która przepełnia, jest , jak pokazano Single.MaxValue PositiveInfinity w poniższym Single.MinValue NegativeInfinity przykładzie.

    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 również wynika z dzielenia przez zero z dodatnią dzielną i wynika z dzielenia przez NegativeInfinity zero z ujemną dzielną.

  • Jeśli operacja zmiennoprzecinkowa jest nieprawidłowa, wynikiem operacji jest NaN . Na przykład NaN wyniki następujących operacji:

    • Dzielenie przez zero z dzielną o wartości zero. Należy pamiętać, że inne przypadki dzielenia przez zero są wynikiem PositiveInfinity wartości lub NegativeInfinity .

    • Dowolna operacja zmiennoprzecinkowa z nieprawidłowymi wejściami. Na przykład próba znalezienia kwadratowego katalogu głównego wartości ujemnej zwraca wartość NaN .

    • Dowolna operacja z argumentem, którego wartość to Single.NaN .

Konwersje typów i pojedyncza struktura

Struktura nie definiuje żadnych jawnych ani niejawnych operatorów Single konwersji; zamiast tego konwersje są implementowane przez kompilator.

W poniższej tabeli wymieniono możliwe konwersje wartości innych pierwotnych typów liczbowych na wartość. Wskazuje ona również, czy konwersja jest poszerzana, czy zawęża, oraz czy wynikowa wartość może mieć mniejszą precyzję niż oryginalna Single Single wartość.

Konwersja z Poszerzanie/zawężanie Możliwa utrata precyzji
Byte Widening Nie
Decimal Widening

Należy pamiętać, że język C# wymaga operatora rzutowania.
Tak. Decimal obsługuje 29 cyfr dziesiętnych precyzji; Single Obsługuje 9.
Double Zawężanie; Wartości poza zakresem są konwertowane na Double.NegativeInfinity lub Double.PositiveInfinity . Tak. Double obsługuje 17 cyfr dziesiętnych precyzji; Single Obsługuje 9.
Int16 Widening Nie
Int32 Widening Tak. Int32 obsługuje 10 cyfr dziesiętnych precyzji; Single Obsługuje 9.
Int64 Widening Tak. Int64 obsługuje 19 cyfr dziesiętnych precyzji; Single Obsługuje 9.
SByte Widening Nie
UInt16 Widening Nie
UInt32 Widening Tak. UInt32 obsługuje 10 cyfr dziesiętnych precyzji; Single Obsługuje 9.
UInt64 Widening Tak. Int64 obsługuje 20 cyfr dziesiętnych precyzji; Single Obsługuje 9.

Poniższy przykład konwertuje wartość minimalną lub maksymalną innych pierwotnych typów liczbowych na Single wartość.

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)

Ponadto wartości , Double i są Double.NaN Double.PositiveInfinity Double.NegativeInfinity konwertowane odpowiednio na Single.NaN Single.PositiveInfinity wartości , i Single.NegativeInfinity .

Należy pamiętać, że konwersja wartości niektórych typów liczbowych na wartość może Single wiązać się z utratą dokładności. Jak pokazano w przykładzie, utrata dokładności jest możliwa podczas konwertowania Decimal wartości , , , , i na Double Int32 Int64 UInt32 UInt64 Single wartości.

Konwersja wartości Single na wartość to Double konwersja poszerzania. Konwersja może spowodować utratę dokładności, jeśli typ nie ma dokładnej reprezentacji Double Single wartości.

Konwersja wartości na wartość dowolnego pierwotnego typu danych liczbowych innych niż a jest konwersją zawężaną i wymaga operatora rzutowania Single (w języku C#) lub metody konwersji Double (w Visual Basic). Wartości spoza zakresu docelowego typu danych, które są definiowane przez właściwości i typ docelowy, zachowują się tak, jak pokazano w MinValue MaxValue poniższej tabeli.

Typ docelowy Wynik
Dowolny typ całkowito-całkowitocowy OverflowExceptionWyjątek, jeśli konwersja ma miejsce w sprawdzonym kontekście.

Jeśli konwersja odbywa się w niesprawdzonym kontekście (wartość domyślna w języku C#), operacja konwersji powiedzie się, ale wartość zostanie przepełniona.
Decimal OverflowExceptionWyjątek,

Ponadto , i zgłaszają dla konwersji na liczby całkowite w kontekście sprawdzane, ale te wartości przepełniają się w przypadku konwersji na liczby całkowite w Single.NaN Single.PositiveInfinity Single.NegativeInfinity OverflowException kontekście niezaznaczonej. W przypadku konwersji Decimal na element zawsze zgłaszany jest element OverflowException . W przypadku konwersji na , konwertują odpowiednio na Double , i Double.NaN Double.PositiveInfinity Double.NegativeInfinity .

Należy pamiętać, że utrata dokładności może wynikać z konwersji wartości Single na inny typ liczbowy. W przypadku konwertowania wartości innych niż całkowitoliczbowe, jak pokazano w przykładzie, składnik ułamkowy jest utracony, gdy wartość jest zaokrąglana (jak w Visual Basic) lub obcinana (jak w Single Single języku C#). W przypadku konwersji na wartości wartość może nie mieć dokładnej reprezentacji Decimal Single w docelowym typie danych.

W poniższym przykładzie liczba wartości jest Single konwertowana na kilka innych typów liczbowych. Konwersje występują w sprawdzonym kontekście w Visual Basic (ustawienie domyślne) i w języku C# (ze względu na sprawdzone słowo kluczowe). Dane wyjściowe z przykładu pokazują wynik konwersji w obu przypadkach zaznaczonego niezaznaczonego kontekstu. Konwersje w niesprawdzonym kontekście można wykonać w Visual Basic, kompilując z przełącznikiem kompilatora i w języku /removeintchecks+ C#, komentowając tę checked instrukcje.

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)

Aby uzyskać więcej informacji na temat konwersji typów liczbowych, zobacz Konwersja typów w tabelach .NET Framework i Type Conversion.

Funkcje zmiennoprzecinkowe

Struktura Single i powiązane typy zapewniają metody wykonywania następujących kategorii operacji:

  • Porównanie wartości. Możesz wywołać metodę , aby określić, czy dwie wartości są równe, lub metodę w celu określenia Equals Single CompareTo relacji między dwiema wartościami.

    Struktura Single obsługuje również kompletny zestaw operatorów porównania. Można na przykład przetestować równość lub nierówność albo określić, czy jedna wartość jest większa lub równa innej wartości. Jeśli jeden z operandów jest argumentem , wartość jest Double Single konwertowana na wartość przed Double wykonaniem porównania. Jeśli jeden z operandów jest typem całkowitoliczbowy, jest on konwertowany na typ przed Single wykonaniem porównania. Chociaż są to konwersje poszerzaające, mogą one wiązać się z utratą dokładności.

    Ostrzeżenie

    Ze względu na różnice w dokładności dwie wartości, które powinny być równe, mogą okazać się nierówne, co wpływa na Single wynik porównania. Zobacz sekcję Testowanie pod względem równości, aby uzyskać więcej informacji na temat porównywania dwóch Single wartości.

    Możesz również wywołać metody IsNaN , , i , aby IsInfinity IsPositiveInfinity IsNegativeInfinity przetestować te wartości specjalne.

  • Operacje matematyczne. Typowe operacje arytmetyczne, takie jak dodawanie, odejmowanie, mnożenie i dzielenie, są implementowane przez kompilatory języka i instrukcje wspólnego języka pośredniego (CIL), a nie Single metody. Jeśli drugim operandem w operacji matematycznej jest , wartość jest konwertowana na wartość przed wykonaniem operacji, a wynik operacji jest Double Single również Double Double wartością. Jeśli drugi operand jest typem całkowitoliczbowy, jest konwertowany na wartość przed wykonaniem operacji, a wynik operacji jest Single również Single wartością.

    Inne operacje matematyczne można wykonywać, wywołując static metody ( Shared w Visual Basic) w klasie System.Math . Obejmują one dodatkowe metody często używane do arytmetyki (np. Math.Abs Math.Sign , i ), geometrii (na przykład i ) oraz rachunku Math.Sqrt Math.Cos Math.Sin (takiego jak Math.Log ). We wszystkich przypadkach wartość Single jest konwertowana na Double wartość .

    Można również manipulować poszczególnymi bitami w Single wartości. Metoda BitConverter.GetBytes(Single) zwraca wzorzec bitowy w tablicy bajtów. Przekazując tę tablicę bajtów do metody , można również zachować wzorzec bitów wartości BitConverter.ToInt32 Single w 32-bitowej całkowitej.

  • Zaokrąglanie . Zaokrąglanie jest często używane jako technika zmniejszania wpływu różnic między wartościami spowodowanych przez problemy z reprezentacją zmiennoprzecinkową i precyzją. Wartość można Single zaokrąglić, wywołując Math.Round metodę . Należy jednak pamiętać, że wartość jest konwertowana na wartość przed wywołaną metodą , a konwersja może obejmować Single Double utratę precyzji.

  • Formatowanie. Wartość można przekonwertować na jej reprezentację w Single postaci ciągu, wywołując ToString metodę lub używając funkcji formatowania złożonego. Aby uzyskać informacje o tym, jak ciągi formatowe kontrolują reprezentację ciągów wartości zmiennoprzecinkowe, zobacz tematy Standardowe ciągi formatów liczbowych i Niestandardowe ciągi formatów liczbowych.

  • Analizowanie ciągów. Reprezentację ciągu wartości zmiennoprzecinkowej można przekonwertować na Single wartość, wywołując Parse metodę lub TryParse . Jeśli operacja analizy zakończy się niepowodzeniem, Parse metoda zgłasza wyjątek, natomiast metoda zwraca wartość TryParse false .

  • Konwersja typu. Struktura Single zapewnia jawną implementację interfejsu IConvertible dla interfejsu, która obsługuje konwersję między dowolnymi dwoma standardowymi .NET Framework typami danych. Kompilatory języka obsługują również niejawną konwersję wartości dla wszystkich innych standardowych typów liczbowych z wyjątkiem konwersji na Double Single wartości. Konwersja wartości dowolnego standardowego typu liczbowego innego niż a na wartość jest konwersją poszerzaną i nie wymaga użycia Double Single operatora rzutowania ani metody konwersji.

    Jednak konwersja 32-bitowych i 64-bitowych wartości całkowitych może wiązać się z utratą dokładności. W poniższej tabeli wymieniono różnice w dokładności dla typów 32-bitowych, 64-bitowych i Double :

    Typ Maksymalna precyzja (w cyfrach dziesiętnych) Precyzja wewnętrzna (w cyfrach dziesiętnych)
    Double 15 17
    Int32 i UInt32 10 10
    Int64 i UInt64 19 19
    Single 7 9

    Problem dokładności najczęściej ma wpływ na Single wartości, które są konwertowane na Double wartości. W poniższym przykładzie dwie wartości produkowane przez identyczne operacje dzielenia są nierówne, ponieważ jedna z tych wartości jest wartością zmiennoprzecinkową o pojedynczej precyzji, która jest konwertowana na 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
    

Pola

Epsilon

Reprezentuje najmniejszą wartość Single dodatnią, która jest większa od zera. To pole jest stałe.

MaxValue

Reprezentuje największą możliwą wartość Single . To pole jest stałe.

MinValue

Reprezentuje najmniejszą możliwą Single wartość . To pole jest stałe.

NaN

Reprezentuje nie liczbę ( NaN ). To pole jest stałe.

NegativeInfinity

Reprezentuje nieskończoność ujemną. To pole jest stałe.

PositiveInfinity

Reprezentuje nieskończoność dodatnią. To pole jest stałe.

Metody

CompareTo(Object)

Porównuje to wystąpienie z określonym obiektem i zwraca liczbę całkowitą, która wskazuje, czy wartość tego wystąpienia jest mniejsza, równa lub większa niż wartość określonego obiektu.

CompareTo(Single)

Porównuje to wystąpienie z określoną liczbą zmiennoprzecinkową pojedynczej precyzji i zwraca liczbę całkowitą, która wskazuje, czy wartość tego wystąpienia jest mniejsza, równa lub większa niż wartość określonej liczby zmiennoprzecinkowej pojedynczej precyzji.

Equals(Object)

Zwraca wartość wskazującą, czy to wystąpienie jest równe podanemu obiektowi.

Equals(Single)

Zwraca wartość wskazującą, czy to wystąpienie i określony Single obiekt reprezentują tę samą wartość.

GetHashCode()

Zwraca wartość skrótu dla tego wystąpienia.

GetTypeCode()

Zwraca wartość TypeCode dla typu wartości Single .

IsFinite(Single)

Określa, czy określona wartość jest skończona (zero, subnormal lub normal).

IsInfinity(Single)

Zwraca wartość wskazującą, czy określona liczba ma wartość ujemną, czy dodatnią nieskończoność.

IsNaN(Single)

Zwraca wartość wskazującą, czy określona wartość nie jest liczbą ( NaN ).

IsNegative(Single)

Określa, czy określona wartość jest ujemna.

IsNegativeInfinity(Single)

Zwraca wartość wskazującą, czy określona liczba daje w przypadku nieskończoności ujemnej.

IsNormal(Single)

Określa, czy określona wartość jest normalna.

IsPositiveInfinity(Single)

Zwraca wartość wskazującą, czy określona liczba daje w stanie nieskończoność dodatnią.

IsSubnormal(Single)

Określa, czy określona wartość jest subnormalna.

Parse(ReadOnlySpan<Char>, NumberStyles, IFormatProvider)

Konwertuje zakres znaków zawierający reprezentację ciągu liczby w określonym stylu i formacie specyficznym dla kultury na równoważnik liczby zmiennoprzecinkowej o pojedynczej precyzji.

Parse(String)

Konwertuje ciąg reprezentujący liczbę na odpowiadającą mu liczbę zmiennoprzecinkową pojedynczej precyzji.

Parse(String, IFormatProvider)

Konwertuje reprezentację ciągu liczby w określonym formacie specyficznym dla kultury na równoważnik liczby zmiennoprzecinkowej o pojedynczej precyzji.

Parse(String, NumberStyles)

Konwertuje reprezentację ciągu liczby w określonym stylu na równoważnik liczby zmiennoprzecinkowym o pojedynczej precyzji.

Parse(String, NumberStyles, IFormatProvider)

Konwertuje reprezentację ciągu liczby w określonym stylu i formacie specyficznym dla kultury na równoważnik liczby zmiennoprzecinkowej o pojedynczej precyzji.

ToString()

Konwertuje wartość liczbową tego wystąpienia na równoważną reprezentację w postaci ciągu.

ToString(IFormatProvider)

Konwertuje wartość liczbową tego wystąpienia na równoważną reprezentację w postaci ciągu przy użyciu podanych danych formatowania specyficznych dla kultury.

ToString(String)

Konwertuje wartość liczbową tego wystąpienia na równoważną reprezentację w postaci ciągu przy użyciu podanego formatu.

ToString(String, IFormatProvider)

Konwertuje wartość liczbową tego wystąpienia na równoważną reprezentację w postaci ciągu przy użyciu podanego formatu i informacji specyficznych dla kultury.

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

Próbuje sformatować wartość bieżącego wystąpienia liczby zmiennoprzecinkowa do podanego zakresu znaków.

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

Konwertuje reprezentację zakresu liczby w określonym stylu i formacie specyficznym dla kultury na równoważnik liczby zmiennoprzecinkowej o pojedynczej precyzji. Zwracana wartość wskazuje, czy konwersja powiodła się czy nie.

TryParse(ReadOnlySpan<Char>, Single)

Konwertuje reprezentację ciągu liczby w zakresu znaków na równoważnik liczby zmiennoprzecinkowej o pojedynczej precyzji. Zwracana wartość wskazuje, czy konwersja powiodła się czy nie.

TryParse(String, NumberStyles, IFormatProvider, Single)

Konwertuje reprezentację ciągu liczby w określonym stylu i formacie specyficznym dla kultury na równoważnik liczby zmiennoprzecinkowej o pojedynczej precyzji. Zwracana wartość wskazuje, czy konwersja powiodła się czy nie.

TryParse(String, Single)

Konwertuje ciąg reprezentujący liczbę na odpowiadającą mu liczbę zmiennoprzecinkową pojedynczej precyzji. Zwracana wartość wskazuje, czy konwersja powiodła się czy nie.

Operatory

Equality(Single, Single)

Zwraca wartość wskazującą, czy dwie określone Single wartości są równe.

GreaterThan(Single, Single)

Zwraca wartość wskazującą, czy określona Single wartość jest większa niż inna Single określona wartość.

GreaterThanOrEqual(Single, Single)

Zwraca wartość wskazującą, czy określona wartość jest większa niż lub Single równa innej określonej Single wartości.

Inequality(Single, Single)

Zwraca wartość wskazującą, czy dwie określone Single wartości nie są równe.

LessThan(Single, Single)

Zwraca wartość wskazującą, czy określona Single wartość jest mniejsza niż inna Single określona wartość.

LessThanOrEqual(Single, Single)

Zwraca wartość wskazującą, czy określona wartość jest mniejsza niż lub Single równa innej określonej Single wartości.

Jawne implementacje interfejsu

IComparable.CompareTo(Object)

Porównuje bieżące wystąpienie z innym obiektem tego samego typu i zwraca liczbę całkowitą, która wskazuje, czy bieżące wystąpienie poprzedza, następuje po lub występuje w tym samym położeniu, co inny obiekt w porządku sortowania.

IConvertible.GetTypeCode()

Zwraca wartość TypeCode dla tego wystąpienia.

IConvertible.ToBoolean(IFormatProvider)

Aby uzyskać opis tego członka, zobacz ToBoolean(IFormatProvider) .

IConvertible.ToByte(IFormatProvider)

Aby uzyskać opis tego członka, zobacz ToByte(IFormatProvider) .

IConvertible.ToChar(IFormatProvider)

Ta konwersja nie jest obsługiwana. Próba użycia tej metody zgłasza wyjątek InvalidCastException .

IConvertible.ToDateTime(IFormatProvider)

Ta konwersja nie jest obsługiwana. Próba użycia tej metody zgłasza wyjątek InvalidCastException .

IConvertible.ToDecimal(IFormatProvider)

Aby uzyskać opis tego członka, zobacz ToDecimal(IFormatProvider) .

IConvertible.ToDouble(IFormatProvider)

Aby uzyskać opis tego członka, zobacz ToDouble(IFormatProvider) .

IConvertible.ToInt16(IFormatProvider)

Aby uzyskać opis tego członka, zobacz ToInt16(IFormatProvider) .

IConvertible.ToInt32(IFormatProvider)

Aby uzyskać opis tego członka, zobacz ToInt32(IFormatProvider) .

IConvertible.ToInt64(IFormatProvider)

Aby uzyskać opis tego członka, zobacz ToInt64(IFormatProvider) .

IConvertible.ToSByte(IFormatProvider)

Aby uzyskać opis tego członka, zobacz ToSByte(IFormatProvider) .

IConvertible.ToSingle(IFormatProvider)

Aby uzyskać opis tego członka, zobacz ToSingle(IFormatProvider) .

IConvertible.ToType(Type, IFormatProvider)

Aby uzyskać opis tego członka, zobacz ToType(Type, IFormatProvider) .

IConvertible.ToUInt16(IFormatProvider)

Aby uzyskać opis tego członka, zobacz ToUInt16(IFormatProvider) .

IConvertible.ToUInt32(IFormatProvider)

Aby uzyskać opis tego członka, zobacz ToUInt32(IFormatProvider) .

IConvertible.ToUInt64(IFormatProvider)

Aby uzyskać opis tego członka, zobacz ToUInt64(IFormatProvider) .

Dotyczy

Bezpieczeństwo wątkowe

Wszystkie elementy członkowskie tego typu są bezpieczne wątkowo. Elementy członkowskie, które na pierwszy rzut oka modyfikują stan wystąpienia, w rzeczywistości zwracają nowe wystąpienie zainicjowane z nową wartością. Podobnie jak w przypadku innych typów odczytywanie i zapisywanie w udostępnionej zmiennej, która zawiera wystąpienie tego typu, musi być chronione przez blokadę w celu zagwarantowania bezpieczeństwa wątków.

Zobacz też