Single Структура

Определение

Представляет число одиночной точности с плавающей запятой.

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
Наследование
Single
Атрибуты
Реализации

Комментарии

SingleТип значения представляет собой 32-разрядное число с одинарной точностью и значениями от отрицательного 3.402823 E38 до положительного 3.402823 E38, а также положительного или отрицательного нуля,, PositiveInfinity NegativeInfinity , а не числа ( NaN ). Он предназначен для представления очень больших значений (например, расстояния между планеты или ГАЛАКСИЕС) или чрезвычайно малым (например, молекулярное масса вещества в килограммах) и часто являются неточными (например, расстояние от земли до другой солнечной системы). SingleТип соответствует стандарту IEC 60559:1989 (IEEE 754) для бинарной арифметики с плавающей запятой.

Эта статья состоит из следующих разделов:

System.Single предоставляет методы для сравнения экземпляров этого типа, преобразования значения экземпляра в строковое представление и преобразования строкового представления числа в экземпляр этого типа. Сведения о том, как коды спецификации формата управляют строковым представлением типов значений, см. в разделе Типы форматирования, строки стандартных числовых форматови строки настраиваемых числовых форматов.

Представление и точность с плавающей точкой

SingleТип данных хранит значения с плавающей запятой одиночной точности в 32-разрядном двоичном формате, как показано в следующей таблице.

Отделение Bits
Значащим или мантисса 0-22
Показатель степени 23-30
Знак (0 = положительный, 1 = отрицательный) 31

Точно так же, как десятичные дроби не могут точно представлять некоторые дробные значения (например, 1/3 или Math.PI ), двоичные дроби не могут представлять некоторые дробные значения. Например, 2/10, которая точно представляется в виде десятичной дроби 2, представляется в виде 0011111001001100 в виде двоичной дроби с шаблоном "1100", повторяющимся до бесконечности. В этом случае значение с плавающей запятой обеспечивает неточное представление числа, которое оно представляет. Выполнение дополнительных математических операций с исходным значением с плавающей запятой часто приводит к нехватке точности. Например, если сравнить результаты умножения 3 на 10 и добавить 3 в. 3 9 раз, вы увидите, что сложение выдает менее точный результат, так как включает восемь дополнительных операций, чем умножение. Обратите внимание, что такое нарушение четности очевидно только при отображении двух Single значений с помощью строки стандартного числового форматаR, которая при необходимости отображает все 9 знаков точности, поддерживаемые Single типом.

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

Поскольку некоторые числа не могут быть представлены в виде дробных двоичных значений, числа с плавающей запятой могут быть приблизительными только вещественными числами.

Все числа с плавающей запятой имеют ограниченное число значащих цифр, что также определяет, насколько точное значение числа с плавающей запятой приблизительно равно вещественному числу. SingleЗначение имеет длину до 7 десятичных разрядов, хотя для внутренних целей поддерживается не более 9 цифр. Это означает, что некоторые операции с плавающей запятой могут не иметь точности изменять значение с плавающей запятой. В следующем примере определяется большое значение с плавающей запятой одиночной точности, а затем к нему добавляется Single.Epsilon и один квадриллион. Однако продукт слишком мал для изменения исходного значения с плавающей запятой. Его минимальная значимая цифра состоит из тысяч, в то время как наиболее значимая цифра в продукте составляет 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

Ограниченная точность числа с плавающей запятой имеет несколько последствий:

  • Два числа с плавающей запятой, которые могут казаться равными при определенной точности, на самом деле отличаются, поскольку их менее значащие цифры различаются. В следующем примере ряд чисел добавляется вместе, а их итог сравнивается с ожидаемым итогом. Хотя два значения выглядят одинаково, вызов Equals метода указывает, что они не являются.

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

    Если изменить элементы форматирования в Console.WriteLine(String, Object, Object) инструкции с {0} и {1} на {0:R} и, {1:R} чтобы отобразить все значащие цифры двух Single значений, то ясно, что эти два значения не равны из-за потери точности во время операций сложения. В этом случае проблему можно устранить, вызвав Math.Round(Double, Int32) метод, чтобы округлить Single значения до нужной точности перед выполнением сравнения.

  • Математическая операция OR, использующая число с плавающей запятой, может не дать одинакового результата, если используется десятичное число, так как число двоичных с плавающей запятой может не совпадать с десятичным числом. Предыдущий пример демонстрирует это, отображая результат умножения 3 на 10 и добавляя 3 в. 3 9 раз.

    Если точность числовых операций с дробными значениями важна, используйте Decimal тип вместо Single типа. Если точность числовых операций с целочисленными значениями вне диапазона Int64 UInt64 типов или важна, используйте BigInteger тип.

  • Значение может не циклически передавалться, если используется число с плавающей запятой. Значение говорит о круговой передаче, если операция преобразует исходное число с плавающей запятой в другую форму, операция обратного преобразования преобразует преобразованную форму обратно в число с плавающей запятой, а окончательное число с плавающей запятой равно исходному числу с плавающей запятой. Цикл обработки может завершиться ошибкой, поскольку одна или несколько наименьших значащих цифр теряются или изменяются при преобразовании. В следующем примере три Single значения преобразуются в строки и сохраняются в файле. Как видно из выходных данных, хотя значения выглядят одинаковыми, восстановленные значения не равны исходным значениям.

    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
    

    В этом случае можно успешно выполнить циклический обмен значениями, используя стандартную строку числового формата "G9" для сохранения полной точности Single значений, как показано в следующем примере.

    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 значения имеют меньшую точность, чем Double значения. SingleЗначение, которое преобразуется в эквивалентный, Double часто не равно Double значению из-за различий в точности. В следующем примере результат идентичных операций деления присваивается Double значению и Single значению. После Single приведения значения к типу 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
    

    Чтобы избежать этой проблемы, либо используйте Double тип данных вместо Single типа данных, либо используйте Round метод, чтобы оба значения имели одинаковую точность.

Проверка на равенство

Чтобы считаться равными, два Single значения должны представлять одинаковые значения. Однако из-за различия в точности между значениями или из-за потери точности по одному или обоим значениям значения с плавающей запятой, которые должны быть идентичными, часто оказываются неравными в связи с различиями в их минимально значащих цифрах. В результате вызовы Equals метода для определения того, равны ли два значения, или вызовы CompareTo метода для определения связи между двумя Single значениями, часто дают непредвиденные результаты. Это очевидно в следующем примере, где два очевидных значения могут Single быть неравными, так как первое значение имеет 7 цифр точности, а второе значение равно 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

Вычисляемые значения, которые следуют разным путям кода и управляются разными способами, часто не считаются равными. В следующем примере одно Single значение помещается в квадрат, а затем вычисляется квадратный корень для восстановления исходного значения. Вторая Single умножается на 3,51 и в квадрате, прежде чем квадратный корень результата делится на 3,51 для восстановления исходного значения. Несмотря на то, что два значения выглядят одинаковыми, вызов Equals(Single) метода указывает, что они не равны. Использование строки стандартного формата "G9" для возврата результирующей строки, отображающей все значащие цифры каждого Single значения, показывает, что второе значение .0000000000001 меньше первого.

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

В случаях, когда вероятность потери точности может повлиять на результат сравнения, вместо вызова метода или можно использовать следующие методы Equals CompareTo :

  • Вызовите Math.Round метод, чтобы убедиться, что оба значения имеют одинаковую точность. Следующий пример изменяет предыдущий пример, чтобы использовать этот подход, чтобы два дробных значения были эквивалентными.

    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
    

    Проблема точности по-прежнему применима к округлению средних значений. Дополнительные сведения см. в описании метода Math.Round(Double, Int32, MidpointRounding).

  • Проверка на приблизительную равенство вместо равенства. Для этого способа необходимо определить абсолютное значение, по которому два значения могут различаться, но по-прежнему быть равными, или определить относительный объем, на который меньшее значение может отличаться от большего.

    Предупреждение

    Single.Epsilon иногда используется в качестве абсолютной меры расстояния между двумя Single значениями при проверке на равенство. Однако Single.Epsilon измеряет наименьшее возможное значение, которое можно добавить или вычесть из, Single значение которого равно нулю. Для большинства положительных и отрицательных Single значений значение Single.Epsilon слишком мало для обнаружения. Таким образом, за исключением нулевых значений, не рекомендуется использовать его в тестах на равенство.

    В следующем примере используется второй подход для определения IsApproximatelyEqual метода, который проверяет относительное различие между двумя значениями. Он также отличается от результата вызовов IsApproximatelyEqual метода и 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
    

Значения и исключения с плавающей запятой

Операции с значениями с плавающей запятой не создают исключения, в отличие от операций с целочисленными типами, которые создают исключения в случае недопустимых операций, таких как деление на ноль или переполнение. Вместо этого в таких ситуациях результат операции с плавающей запятой равен нулю, плюс бесконечность, отрицательная бесконечность или не является числом (NaN):

  • Если результат операции с плавающей запятой слишком мал для конечного формата, результат равен нулю. Это может произойти при умножении двух очень маленьких чисел с плавающей запятой, как показано в следующем примере.

    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
    
  • Если величина результата операции с плавающей запятой превышает диапазон формата назначения, результатом операции будет PositiveInfinity или NegativeInfinity , в зависимости от знака результата. Результатом операции, которая переполняется Single.MaxValue PositiveInfinity , является, а результатом операции, которая переполняется, Single.MinValue является NegativeInfinity , как показано в следующем примере.

    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 также результаты из деления на ноль с положительным делимым и NegativeInfinity результатом деления на ноль с отрицательным делимым.

  • Если операция с плавающей запятой является недопустимой, результатом операции будет NaN . Например, NaN результаты выполнения следующих операций:

    • Деление на ноль с делимым на ноль. Обратите внимание, что другие варианты деления на ноль приводят к одному PositiveInfinity или NegativeInfinity .

    • Любая операция с плавающей запятой с недопустимыми входными данными. Например, при попытке найти квадратный корень из отрицательного значения возвращается значение NaN .

    • Любая операция с аргументом, значение которого равно Single.NaN .

Преобразования типов и единая структура

В Single структуре не определены явные или неявные операторы преобразования. вместо этого преобразования реализуются компилятором.

В следующей таблице перечислены возможные преобразования значения других примитивных числовых типов в Single значение, а также указывает, является ли преобразование расширяющимся или сужающим, и может ли результирующий объект Single иметь меньшую точность, чем исходное значение.

Допустимо ли преобразование из Расширяющие и узкие Возможная потери точности
Byte Widening Нет
Decimal Widening

Обратите внимание, что в C# требуется оператор CAST.
Да. Decimal поддерживает 29 десятичных разрядов точности; Single поддерживает 9.
Double Сужающие значения вне диапазона преобразуются в Double.NegativeInfinity или Double.PositiveInfinity . Да. Double поддерживает 17 десятичных разрядов точности; Single поддерживает 9.
Int16 Widening Нет
Int32 Widening Да. Int32 поддерживает 10 десятичных разрядов точности; Single поддерживает 9.
Int64 Widening Да. Int64 поддерживает 19 десятичных разрядов точности; Single поддерживает 9.
SByte Widening Нет
UInt16 Widening Нет
UInt32 Widening Да. UInt32 поддерживает 10 десятичных разрядов точности; Single поддерживает 9.
UInt64 Widening Да. Int64 поддерживает 20 десятичных разрядов точности; Single поддерживает 9.

В следующем примере минимальное или максимальное значение других примитивных числовых типов преобразуется в Single значение.

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)

Кроме того, Double значения, Double.NaN Double.PositiveInfinity и Double.NegativeInfinity преобразуются в Single.NaN , Single.PositiveInfinity и Single.NegativeInfinity соответственно.

Обратите внимание, что преобразование значения некоторых числовых типов в Single значение может привести к утрате точности. Как показано в примере, возможна утрата точности при преобразовании значений,,,, Decimal Double Int32 Int64 UInt32 и UInt64 в Single значения.

Преобразование Single значения в Double является расширяющим преобразованием. Преобразование может привести к утрате точности, если тип не Double имеет точного представления Single значения.

Преобразование Single значения в значение любого типа данных-примитива, отличного от, представляет собой Double понижающие преобразования и требует оператора приведения (в C#) или метода преобразования (в Visual Basic). Значения, находящиеся за пределами диапазона целевого типа данных, определяемые MinValue свойствами и свойств целевого типа MaxValue , ведут себя так, как показано в следующей таблице.

Тип результирующего значения Результат
Любой целочисленный тип OverflowExceptionИсключение, если преобразование происходит в проверяемом контексте.

Если преобразование происходит в непроверяемом контексте (по умолчанию в C#), операция преобразования выполняется успешно, но значение переполняется.
Decimal OverflowExceptionИсключение,

Кроме того, Single.NaN , Single.PositiveInfinity и Single.NegativeInfinity вызывают OverflowException для преобразования в целые числа в проверяемом контексте, но эти значения переполняются при преобразовании в целые числа в непроверяемом контексте. Для преобразований Decimal они всегда создают исключение OverflowException . Для преобразований Double они преобразуют в Double.NaN , Double.PositiveInfinity и Double.NegativeInfinity соответственно.

Обратите внимание, что при преобразовании Single значения в другой числовой тип может произойти утрата точности. в случае преобразования нецелочисленных Single значений, как показано в выходных данных примера, дробный компонент теряется, если Single значение округляется (как в Visual Basic) или усекается (как в C#). Для преобразований в Decimal значения Single значение может не иметь точного представления в целевом типе данных.

В следующем примере число значений преобразуется Single в несколько других числовых типов. преобразования выполняются в проверяемом контексте в Visual Basic (по умолчанию) и в C# (из-за ключевого слова checked ). Выходные данные в примере показывают результат для преобразований в проверяемом непроверяемом контексте. вы можете выполнять преобразования в непроверенном контексте в Visual Basic путем компиляции с помощью /removeintchecks+ параметра компилятора и в C#, закомментируя checked инструкцию.

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)

дополнительные сведения о преобразовании числовых типов см. в разделе преобразование типов в таблицах платформа .NET Framework и преобразования типов.

Функция вычислений с плавающей запятой

SingleСтруктура и связанные типы предоставляют методы для выполнения следующих категорий операций:

  • Сравнение значений. Можно вызвать метод, Equals чтобы определить Single , равны ли два значения, или CompareTo метод для определения связи между двумя значениями.

    SingleСтруктура также поддерживает полный набор операторов сравнения. Например, можно проверить на равенство или неравенство или определить, является ли одно значение больше или равно другому значению. Если один из операндов — Double , Single значение преобразуется в Double перед выполнением сравнения. Если один из операндов является целочисленным типом, Single перед выполнением сравнения он преобразуется в. Хотя это расширяющие преобразования, они могут привести к утрате точности.

    Предупреждение

    Из-за различий в точности два Single значения, которые должны быть равны, могут быть неравными, что влияет на результат сравнения. Дополнительные сведения о сравнении двух значений см. в разделе Проверка на равенство Single .

    IsNaN IsInfinity IsPositiveInfinity IsNegativeInfinity Для проверки этих специальных значений можно также вызвать методы,, и.

  • Математические операции. Распространенные арифметические операции, такие как сложение, вычитание, умножение и деление, реализуются компиляторами языка и инструкциями на языке CIL, а не Single методами. Если другой операнд в математической операции — Double , Single Double перед выполнением операции преобразуется в, а результатом операции также является Double значение. Если другой операнд является целочисленным типом, он преобразуется в Single перед выполнением операции, а результат операции также является Single значением.

    можно выполнять другие математические операции, вызывая static Shared методы (в Visual Basic) в System.Math классе. К ним относятся дополнительные методы, обычно используемые для арифметических операций (например Math.Abs ,, Math.Sign и Math.Sqrt ), Geometry (например, Math.Cos и Math.Sin ) и математического анализа за (например, Math.Log ). Во всех случаях Single значение преобразуется в Double .

    Можно также манипулировать отдельными битами Single значения. BitConverter.GetBytes(Single)Метод возвращает свой битовый шаблон в массиве байтов. Передавая этот массив байтов в BitConverter.ToInt32 метод, можно также сохранить Single битовый шаблон значения в 32-битовом целом формате.

  • Округление. Округление часто используется как метод снижения влияния различий между значениями, вызванными проблемами представления и точности с плавающей запятой. Можно округлить Single значение, вызвав Math.Round метод. Однако обратите внимание, что Single значение преобразуется в Double перед вызовом метода, а преобразование может привести к утрате точности.

  • Форматирование. Значение можно преобразовать Single в строковое представление, вызвав ToString метод или воспользовавшись функцией составного форматирования . Сведения о том, как строки формата управляют строковым представлением значений с плавающей запятой, см. в разделах стандартные строки числовых форматов и строки настраиваемых числовых форматов .

  • Синтаксический анализ строк. Можно преобразовать строковое представление значения с плавающей запятой в Single значение, вызвав Parse TryParse метод или. Если операция синтаксического анализа завершается неудачно, Parse метод создает исключение, в то время как TryParse метод возвращает false .

  • Преобразование типов. Singleструктура предоставляет явную реализацию интерфейса для IConvertible интерфейса, который поддерживает преобразование между любыми двумя стандартными платформа .NET Frameworkными типами данных. Языковые компиляторы также поддерживают неявное преобразование значений для всех других стандартных числовых типов, за исключением преобразования Double в Single значения. Преобразование значения любого стандартного числового типа, отличного от, Double в Single , является расширяющим преобразованием и не требует использования оператора приведения или метода преобразования.

    Однако преобразование 32-разрядных и 64-разрядных целочисленных значений может привести к утрате точности. В следующей таблице перечислены различия в точности для 32-разрядных, 64-разрядных и Double типов:

    Type Максимальная точность (в десятичных цифрах) Внутренняя точность (в десятичных цифрах)
    Double 15 17
    Int32 и UInt32 10 10
    Int64 и UInt64 19 19
    Single 7 9

    Проблема точности чаще всего влияет на Single значения, которые преобразуются в Double значения. В следующем примере два значения, созданные идентичными операциями деления, не равны, так как одно из значений является значением с плавающей запятой одиночной точности, которое преобразуется в 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
    

Поля

Epsilon

Представляет наименьшее положительное значение Single больше нуля. Это поле является константой.

MaxValue

Представляет наибольшее возможное значение типа Single. Это поле является константой.

MinValue

Представляет минимально допустимое значение типа Single. Это поле является константой.

NaN

Представляет нечисловое значение (NaN). Это поле является константой.

NegativeInfinity

Представляет минус бесконечность. Это поле является константой.

PositiveInfinity

Представляет плюс бесконечность. Это поле является константой.

Методы

CompareTo(Object)

Сравнивает данный экземпляр с указанным объектом и возвращает целое число, которое показывает, является ли значение данного экземпляра меньше, больше или равно значению заданного объекта.

CompareTo(Single)

Сравнивает данный экземпляр с заданным числом одиночной точности с плавающей запятой и возвращает целое число, которое показывает, является ли значение данного экземпляра меньше, больше или равным значению заданного числа одиночной точности с плавающей запятой.

Equals(Object)

Возвращает значение, показывающее, равен ли данный экземпляр заданному объекту.

Equals(Single)

Возвращает значение, позволяющее определить, представляют ли этот экземпляр и заданный объект Single одно и то же значение.

GetHashCode()

Возвращает хэш-код данного экземпляра.

GetTypeCode()

Возвращает TypeCode для типа значения Single.

IsFinite(Single)

Определяет, является ли указанное значение конечным (нулевым, поднормальным или нормальным).

IsInfinity(Single)

Возвращает значение, позволяющее определить, равно ли данное число плюс или минус бесконечности.

IsNaN(Single)

Возвращает значение, показывающее, что указанное значение не является числом (NaN).

IsNegative(Single)

Определяет, является ли заданное значение отрицательным.

IsNegativeInfinity(Single)

Возвращает значение, позволяющее определить, равно ли данное число минус бесконечности.

IsNormal(Single)

Определяет, является ли заданное значение нормальным.

IsPositiveInfinity(Single)

Возвращает значение, показывающее, равно ли данное число плюс бесконечности.

IsSubnormal(Single)

Определяет, является ли заданное значение поднормальным.

Parse(ReadOnlySpan<Char>, NumberStyles, IFormatProvider)

Преобразует диапазон символов, содержащий строковое представление числа в указанном стиле и с использованием формата, соответствующего данному языку и региональным параметрам, в эквивалентное ему число одиночной точности с плавающей запятой.

Parse(String)

Преобразует строковое представление числа в эквивалентное ему число с плавающей запятой одиночной точности.

Parse(String, IFormatProvider)

Преобразует строковое представление числа, записанное в формате, соответствующем определенному языку и региональным параметрам, в эквивалентное ему число одиночной точности с плавающей запятой.

Parse(String, NumberStyles)

Преобразует строковое представление числа в указанном стиле в эквивалентное ему число одиночной точности с плавающей запятой.

Parse(String, NumberStyles, IFormatProvider)

Преобразует строковое представление числа в указанном стиле и с использованием формата, соответствующего данному языку и региональным параметрам, в эквивалентное ему число с плавающей запятой одиночной точности.

ToString()

Преобразует числовое значение данного экземпляра в эквивалентное ему строковое представление.

ToString(IFormatProvider)

Преобразует числовое значение данного экземпляра в эквивалентное ему строковое представление с использованием указанных сведений об особенностях форматирования для данного языка и региональных параметров.

ToString(String)

Преобразует числовое значение данного экземпляра в эквивалентное строковое представление с использованием указанного формата.

ToString(String, IFormatProvider)

Преобразует числовое значение данного экземпляра в эквивалентное ему строковое представление с использованием указанного формата и сведений об особенностях форматирования для данного языка и региональных параметров.

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

Пытается форматировать значение текущего экземпляра числа с плавающей запятой в указанный диапазон символов.

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

Преобразует представление диапазона числа в указанном стиле и с использованием формата, соответствующего данному языку и региональным параметрам, в эквивалентное ему число одиночной точности с плавающей запятой. Возвращает значение, указывающее, успешно ли выполнено преобразование.

TryParse(ReadOnlySpan<Char>, Single)

Преобразует строковое представление числа в диапазоне символов в эквивалентное ему число одиночной точности с плавающей запятой. Возвращает значение, указывающее, успешно ли выполнено преобразование.

TryParse(String, NumberStyles, IFormatProvider, Single)

Преобразует строковое представление числа в указанном стиле и с использованием формата, соответствующего данному языку и региональным параметрам, в эквивалентное ему число одиночной точности с плавающей запятой. Возвращает значение, указывающее, успешно ли выполнено преобразование.

TryParse(String, Single)

Преобразует строковое представление числа в эквивалентное ему число одиночной точности с плавающей запятой. Возвращает значение, указывающее, успешно ли выполнено преобразование.

Операторы

Equality(Single, Single)

Возвращает значение, указывающее, равны ли два заданных значения Single.

GreaterThan(Single, Single)

Возвращает значение, указывающее, действительно ли заданное значение Single больше другого заданного значения Single.

GreaterThanOrEqual(Single, Single)

Возвращает значение, указывающее, действительно ли заданное значение Single больше или равно другому заданному значению Single.

Inequality(Single, Single)

Возвращает значение, указывающее, не равны ли два заданных значения Single.

LessThan(Single, Single)

Возвращает значение, указывающее, действительно ли заданное значение Single меньше другого заданного значения Single.

LessThanOrEqual(Single, Single)

Возвращает значение, указывающее, действительно ли заданное значение Single меньше или равно другому заданному значению Single.

Явные реализации интерфейса

IComparable.CompareTo(Object)

Сравнивает текущий экземпляр с другим объектом того же типа и возвращает целое число, которое показывает, расположен ли текущий экземпляр перед, после или на той же позиции в порядке сортировки, что и другой объект.

IConvertible.GetTypeCode()

Возвращает TypeCode для этого экземпляра.

IConvertible.ToBoolean(IFormatProvider)

Описание этого члена см. в разделе ToBoolean(IFormatProvider).

IConvertible.ToByte(IFormatProvider)

Описание этого члена см. в разделе ToByte(IFormatProvider).

IConvertible.ToChar(IFormatProvider)

Это преобразование не поддерживается. При попытке использовать этот метод выбрасывается исключение InvalidCastException.

IConvertible.ToDateTime(IFormatProvider)

Это преобразование не поддерживается. При попытке использовать этот метод выбрасывается исключение InvalidCastException.

IConvertible.ToDecimal(IFormatProvider)

Описание этого члена см. в разделе ToDecimal(IFormatProvider).

IConvertible.ToDouble(IFormatProvider)

Описание этого члена см. в разделе ToDouble(IFormatProvider).

IConvertible.ToInt16(IFormatProvider)

Описание этого члена см. в разделе ToInt16(IFormatProvider).

IConvertible.ToInt32(IFormatProvider)

Описание этого члена см. в разделе ToInt32(IFormatProvider).

IConvertible.ToInt64(IFormatProvider)

Описание этого члена см. в разделе ToInt64(IFormatProvider).

IConvertible.ToSByte(IFormatProvider)

Описание этого члена см. в разделе ToSByte(IFormatProvider).

IConvertible.ToSingle(IFormatProvider)

Описание этого члена см. в разделе ToSingle(IFormatProvider).

IConvertible.ToType(Type, IFormatProvider)

Описание этого члена см. в разделе ToType(Type, IFormatProvider).

IConvertible.ToUInt16(IFormatProvider)

Описание этого члена см. в разделе ToUInt16(IFormatProvider).

IConvertible.ToUInt32(IFormatProvider)

Описание этого члена см. в разделе ToUInt32(IFormatProvider).

IConvertible.ToUInt64(IFormatProvider)

Описание этого члена см. в разделе ToUInt64(IFormatProvider).

Применяется к

Потокобезопасность

Все члены этого типа являются потокобезопасными. Члены, которые могут изменить состояние экземпляра, в действительности возвращают новый экземпляр, инициализированный новым значением. Как с любым другим типом, чтение и запись общей переменной, которая содержит экземпляр этого типа, должны быть защищены блокировкой для обеспечения потокобезопасности.

См. также раздел