System.Single yapısı

Bu makale, bu API'nin başvuru belgelerine ek açıklamalar sağlar.

Değer Single türü, negatif 3,402823e38 ile pozitif 3,402823e38 arasında değişen değerlerin yanı sıra, sayı (NaN) yerine pozitif veya negatif sıfır, PositiveInfinity, NegativeInfinityve değerleriyle tek duyarlıklı 32 bitlik bir sayıyı temsil eder. Son derece büyük (gezegenler veya galaksiler arasındaki mesafeler gibi) veya son derece küçük (kilogram cinsinden bir maddenin moleküler kütlesi gibi) ve genellikle belirsiz olan (örneğin, dünyadan başka bir güneş sistemine olan uzaklık) değerleri temsil etmeye yöneliktir. Türü, Single ikili kayan nokta aritmetiği için IEC 60559:1989 (IEEE 754) standardına uygundur.

System.Single bu türün örneklerini karşılaştırmak, örneğin değerini dize gösterimine dönüştürmek ve bir sayının dize gösterimini bu türün bir örneğine dönüştürmek için yöntemler sağlar. Biçim belirtim kodlarının değer türlerinin dize gösterimini nasıl denetlediğini öğrenmek için bkz . Biçimlendirme Türleri, Standart Sayısal Biçim Dizeleri ve Özel Sayısal Biçim Dizeleri.

Kayan nokta gösterimi ve duyarlık

Veri türü, Single aşağıdaki tabloda gösterildiği gibi tek duyarlıklı kayan nokta değerlerini 32 bit ikili biçimde depolar:

Bölüm Bits
İşaret veya mantis 0-22
Üs 23-30
İşaret (0 = pozitif, 1 = negatif) 31

Ondalık kesirlerin bazı kesirli değerleri (1/3 veya Math.PIgibi) tam olarak temsil edemediği gibi, ikili kesirler de bazı kesirli değerleri temsil edemez. Örneğin, ondalık kesir olarak tam olarak .2 ile temsil edilen 2/10, .0011111001001100 ile ikili kesir olarak gösterilir ve "1100" deseni sonsuza kadar yineleniyor. Bu durumda kayan nokta değeri, temsil ettiği sayının kesin bir gösterimini sağlar. Özgün kayan nokta değeri üzerinde ek matematiksel işlemler gerçekleştirmek genellikle duyarlık eksikliğini artırır. Örneğin, .3'ün 10 ile çarpıp 0,3 ile 0,3'e dokuz kez eklenmesinin sonuçlarını karşılaştırırsanız, çarpmaya göre sekiz işlem daha içerdiğinden toplama işleminin daha az kesin sonuç ürettiğini görürsünüz. Bu eşitsizliğin, yalnızca "R" standart sayısal biçim dizesini kullanarak görüntülerseniz Single görünür olduğunu unutmayın; gerekirse, türü tarafından Single desteklenen 9 duyarlık basamaklarının tümünü görüntüler.

using System;

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

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

printfn $".2 * 10:           {result1:R}"
printfn $".2 Added 10 times: {result2:R}"
// The example displays the following output:
//       .2 * 10:           2
//       .2 Added 10 times: 2.00000024
Module Example13
    Public Sub Main()
        Dim value As Single = 0.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

Bazı sayılar tam olarak kesirli ikili değerler olarak temsil edilemediği için kayan noktalı sayılar yalnızca gerçek sayılara yakın olabilir.

Tüm kayan nokta sayıları sınırlı sayıda anlamlı basamağı vardır ve bu da kayan nokta değerinin gerçek bir sayıya ne kadar doğru yakın olduğunu belirler. Bir Single değerin en fazla 7 ondalık basamak duyarlık değeri vardır, ancak dahili olarak en fazla 9 basamak korunur. Bu, bazı kayan nokta işlemlerinin kayan nokta değerini değiştirme duyarlığından yoksun olabileceği anlamına gelir. Aşağıdaki örnek, büyük bir tek duyarlıklı kayan nokta değerini tanımlar ve ardından ürününe ve bir katrilyon ekler Single.Epsilon . Ancak, ürün özgün kayan nokta değerini değiştirmek için çok küçük. En az önemli rakamı binde bir, üründeki en önemli rakam ise 10-30 arasıdır.

using System;

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

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

Kayan noktalı bir sayının sınırlı duyarlığı çeşitli sonuçlara neden olur:

  • Belirli bir duyarlık için eşit görünen iki kayan noktalı sayı, en az önemli basamakları farklı olduğundan eşit olarak karşılaştırılamayabilir. Aşağıdaki örnekte, bir dizi sayı bir araya eklenir ve bunların toplamı beklenen toplamlarıyla karşılaştırılır. İki değer aynı gibi görünse de, yöntemine yapılan Equals bir çağrı bunların olmadığını gösterir.

    using System;
    
    public class Example9
    {
        public static void Main()
        {
            Single[] values = { 10.01f, 2.88f, 2.88f, 2.88f, 9.0f };
            Single result = 27.65f;
            Single total = 0f;
            foreach (var value in values)
                total += value;
    
            if (total.Equals(result))
                Console.WriteLine("The sum of the values equals the total.");
            else
                Console.WriteLine("The sum of the values ({0}) does not equal the total ({1}).",
                                  total, result);
        }
    }
    // The example displays the following output:
    //      The sum of the values (27.65) does not equal the total (27.65).   
    //
    // If the index items in the Console.WriteLine statement are changed to {0:R},
    // the example displays the following output:
    //       The sum of the values (27.6500015) does not equal the total (27.65).
    
    let values = [| 10.01f; 2.88f; 2.88f; 2.88f; 9f |]
    let result = 27.65f
    let mutable total = 0f
    for value in values do
        total <- total + value
    
    if total.Equals result then
        printfn "The sum of the values equals the total."
    else
        printfn "The sum of the values ({total}) does not equal the total ({result})."
    // The example displays the following output:
    //      The sum of the values (27.65) does not equal the total (27.65).   
    //
    // If the index items in the Console.WriteLine statement are changed to {0:R},
    // the example displays the following output:
    //       The sum of the values (27.6500015) does not equal the total (27.65).
    
    Module Example10
        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).
    

    İki değerin Console.WriteLine(String, Object, Object) tüm önemli basamaklarını Single görüntülemek için {0:R}{1:R} ve {1} içindeki biçim {0} öğelerini değiştirirseniz, toplama işlemleri sırasında duyarlık kaybı nedeniyle iki değerin eşit olmadığı açıktır. Bu durumda, karşılaştırmayı gerçekleştirmeden önce değerleri istenen duyarlık düzeyine yuvarlama Single yöntemini çağırarak Math.Round(Double, Int32) sorun çözülebilir.

  • Kayan noktalı sayı kullanan bir matematik veya karşılaştırma işlemi, ondalık sayı kullanıldığında aynı sonucu vermeyebilir çünkü ikili kayan noktalı sayı ondalık sayıya eşit olmayabilir. Önceki bir örnek, .3 değerinin 10 ile çarpımının sonucunu görüntüleyerek ve dokuz kez .3'e 0,3 ekleyerek bunu göstermiş.

    Kesirli değerler içeren sayısal işlemlerde doğruluk önemliyse, türü yerine Single türünü kullanınDecimal. veya türlerinin aralığını Int64 aşan tamsayı değerlerine sahip sayısal işlemlerde doğruluk önemliyse, türünü kullanınBigInteger.UInt64

  • Kayan noktalı bir sayı söz konusu olduğunda değer gidiş dönüş olmayabilir. Bir işlem özgün kayan nokta numarasını başka bir forma dönüştürürse, ters işlem dönüştürülen formu kayan noktalı sayıya geri dönüştürürse ve son kayan nokta sayısı özgün kayan nokta numarasına eşitse, değer gidiş dönüş olarak söylenir. Dönüşümde bir veya daha az önemli basamak kaybolduğundan veya değiştirildiğinden gidiş dönüş başarısız olabilir. Aşağıdaki örnekte, üç Single değer dizelere dönüştürülür ve bir dosyaya kaydedilir. Çıktıda gösterildiği gibi, değerler aynı gibi görünse de, geri yüklenen değerler özgün değerlere eşit değildir.

    using System;
    using System.IO;
    
    public class Example10
    {
        public static void Main()
        {
            StreamWriter sw = new StreamWriter(@".\Singles.dat");
            Single[] values = { 3.2f / 1.11f, 1.0f / 3f, (float)Math.PI };
            for (int ctr = 0; ctr < values.Length; ctr++)
            {
                sw.Write(values[ctr].ToString());
                if (ctr != values.Length - 1)
                    sw.Write("|");
            }
            sw.Close();
    
            Single[] restoredValues = new Single[values.Length];
            StreamReader sr = new StreamReader(@".\Singles.dat");
            string temp = sr.ReadToEnd();
            string[] tempStrings = temp.Split('|');
            for (int ctr = 0; ctr < tempStrings.Length; ctr++)
                restoredValues[ctr] = Single.Parse(tempStrings[ctr]);
    
            for (int ctr = 0; ctr < values.Length; ctr++)
                Console.WriteLine("{0} {2} {1}", values[ctr],
                                  restoredValues[ctr],
                                  values[ctr].Equals(restoredValues[ctr]) ? "=" : "<>");
        }
    }
    // The example displays the following output:
    //       2.882883 <> 2.882883
    //       0.3333333 <> 0.3333333
    //       3.141593 <> 3.141593
    
    open System
    open System.IO
    
    let values = [| 3.2f / 1.11f; 1f / 3f; MathF.PI |]
    
    do
        use sw = new StreamWriter(@".\Singles.dat")
        for i = 0 to values.Length - 1 do
            sw.Write(string values[i])
            if i <> values.Length - 1 then
                sw.Write "|"
    
    let restoredValues =
        use sr = new StreamReader(@".\Singles.dat")
        sr.ReadToEnd().Split '|'
        |> Array.map Single.Parse
    
    for i = 0 to values.Length - 1 do
        printfn $"""{values[i]} {if values[i].Equals restoredValues[i] then "=" else "<>"} {restoredValues[i]}"""
                        
    // The example displays the following output:
    //       2.882883 <> 2.882883
    //       0.3333333 <> 0.3333333
    //       3.141593 <> 3.141593
    
    Imports System.IO
    
    Module Example11
        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
    

    Bu durumda, aşağıdaki örnekte gösterildiği gibi değerlerin tam duyarlığı Single korumak için "G9" standart sayısal biçim dizesi kullanılarak değerler başarıyla yuvarlanabilir.

    using System;
    using System.IO;
    
    public class Example11
    {
        public static void Main()
        {
            StreamWriter sw = new StreamWriter(@".\Singles.dat");
            Single[] values = { 3.2f / 1.11f, 1.0f / 3f, (float)Math.PI };
            for (int ctr = 0; ctr < values.Length; ctr++)
                sw.Write("{0:G9}{1}", values[ctr], ctr < values.Length - 1 ? "|" : "");
    
            sw.Close();
    
            Single[] restoredValues = new Single[values.Length];
            StreamReader sr = new StreamReader(@".\Singles.dat");
            string temp = sr.ReadToEnd();
            string[] tempStrings = temp.Split('|');
            for (int ctr = 0; ctr < tempStrings.Length; ctr++)
                restoredValues[ctr] = Single.Parse(tempStrings[ctr]);
    
            for (int ctr = 0; ctr < values.Length; ctr++)
                Console.WriteLine("{0} {2} {1}", values[ctr],
                                  restoredValues[ctr],
                                  values[ctr].Equals(restoredValues[ctr]) ? "=" : "<>");
        }
    }
    // The example displays the following output:
    //       2.882883 = 2.882883
    //       0.3333333 = 0.3333333
    //       3.141593 = 3.141593
    
    open System
    open System.IO
    
    let values = [| 3.2f / 1.11f; 1f / 3f; MathF.PI |]
    
    do
        use sw = new StreamWriter(@".\Singles.dat")
        for i = 0 to values.Length - 1 do
            sw.Write $"""{values[i]:G9}{if i < values.Length - 1 then "|" else ""}"""
        
        
    let restoredValues =
        use sr = new StreamReader(@".\Singles.dat")
        sr.ReadToEnd().Split '|'
        |> Array.map Single.Parse
    
    for i = 0 to values.Length - 1 do
        printfn $"""{values[i]} {if values[i].Equals restoredValues[i] then "=" else "<>"} {restoredValues[i]}"""
    // The example displays the following output:
    //       2.882883 = 2.882883
    //       0.3333333 = 0.3333333
    //       3.141593 = 3.141593
    
    Imports System.IO
    
    Module Example12
        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 değerlerin duyarlığı değerlerden daha Double azdır. Single Eşit gibi Double görünen bir değere dönüştürülen bir değer, duyarlık farklılıkları nedeniyle genellikle değere eşit Double değildir. Aşağıdaki örnekte, aynı bölme işlemlerinin sonucu bir Double değere ve bir Single değere atanır. Single değeri bir Doubledeğerine atandıktan sonra, iki değerin karşılaştırması bunların eşit olmadığını gösterir.

    using System;
    
    public class Example9
    {
        public static void Main()
        {
            Double value1 = 1 / 3.0;
            Single sValue2 = 1 / 3.0f;
            Double value2 = (Double)sValue2;
            Console.WriteLine("{0:R} = {1:R}: {2}", value1, value2,
                                                value1.Equals(value2));
        }
    }
    // The example displays the following output:
    //        0.33333333333333331 = 0.3333333432674408: False
    
    open System
    
    let value1 = 1. / 3.
    let sValue2 = 1f /3f
    
    let value2 = double sValue2
    printfn $"{value1:R} = {value2:R}: {value1.Equals value2}"
    // The example displays the following output:
    //        0.33333333333333331 = 0.3333333432674408: False
    
    Module Example10
        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
    

    Bu sorunu önlemek için, veri türünün yerine veri türünü kullanın Double veya her iki değerin Single de aynı duyarlıkta sahip olması için yöntemini kullanın Round .

Eşitlik testi

Eşit olarak kabul edilmesi için iki Single değerin aynı değerleri temsil etmesi gerekir. Ancak, değerler arasındaki duyarlık farklılıkları nedeniyle veya bir veya her iki değere göre duyarlık kaybı nedeniyle, özdeş olması beklenen kayan nokta değerleri genellikle en az önemli basamaklarındaki farklılıklar nedeniyle eşit değildir. Sonuç olarak, iki değerin Equals eşit olup olmadığını belirlemek için yöntemine CompareTo çağrılar veya iki Single değer arasındaki ilişkiyi belirlemek için yöntemine çağrılar, genellikle beklenmeyen sonuçlar verir. Bu, aşağıdaki örnekte, ilk değerin 7 basamaklı duyarlık, ikinci değerin ise 9 basamaklı olması nedeniyle eşit olmayan iki eşit Single değer olduğu açıktır.

using System;

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

Farklı kod yollarını izleyen ve farklı şekillerde işlenen hesaplanan değerlerin genellikle eşit olmadığını kanıtlar. Aşağıdaki örnekte bir Single değerin karesi alınır ve ardından özgün değeri geri yüklemek için karekök hesaplanır. Bir saniye Single 3,51 ile çarpılır ve sonucun karekökünün özgün değeri geri yüklemek için 3,51'e bölünmesi gerekir. İki değer aynı gibi görünse de, yöntemine yapılan Equals(Single) bir çağrı bunların eşit olmadığını gösterir. Her Single değerin tüm önemli basamaklarını görüntüleyen bir sonuç dizesi döndürmek için "G9" standart biçim dizesini kullanmak, ikinci değerin birinciden .0000000000001 daha küçük olduğunu gösterir.

using System;

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

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

printfn $"{value1} = {value2}: {value1.Equals value2}\n" 
printfn $"{value1:G9} = {value2:G9}"
// The example displays the following output:
//       10.20144 = 10.20144: False
//       
//       10.201438 = 10.2014389
Module Example2
    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

Bir duyarlık kaybının karşılaştırmanın sonucunu etkileyeceği durumlarda, veya CompareTo yöntemini çağırmak Equals yerine aşağıdaki teknikleri kullanabilirsiniz:

  • Her iki değerin Math.Round de aynı duyarlıkta sahip olduğundan emin olmak için yöntemini çağırın. Aşağıdaki örnek, önceki bir örneği bu yaklaşımı kullanacak şekilde değiştirerek iki kesirli değerin eşdeğer olmasını sağlar.

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

    Duyarlık sorunu orta nokta değerlerini yuvarlama için de geçerlidir. Daha fazla bilgi için yöntemine Math.Round(Double, Int32, MidpointRounding) bakın.

  • Eşitlik yerine yaklaşık eşitlik testi yapın. Bu teknik, iki değerin farklı ancak yine de eşit olabileceği mutlak bir tutar tanımlamanızı veya daha küçük değerin daha büyük değerden ayrışabileceği göreli bir miktar tanımlamanızı gerektirir.

    Uyarı

    Single.Epsilon bazen eşitlik testi sırasında iki Single değer arasındaki uzaklığın mutlak ölçüsü olarak kullanılır. Ancak, Single.Epsilon değeri sıfır olan bir Single öğesine eklenebilecek veya çıkarılabilecek en küçük olası değeri ölçer. Çoğu pozitif ve negatif Single değer için değeri Single.Epsilon algılanamaz kadar küçüktür. Bu nedenle, sıfır olan değerler dışında, eşitlik için testlerde kullanılmasını önermeyiz.

    Aşağıdaki örnek, iki değer arasındaki göreli farkı test eden bir IsApproximatelyEqual yöntem tanımlamak için ikinci yaklaşımı kullanır. Ayrıca yöntemine ve yöntemine yapılan çağrıların IsApproximatelyEqual sonucunu da karşıttır Equals(Single) .

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

Kayan nokta değerleri ve özel durumlar

Kayan nokta değerlerine sahip işlemler, sıfıra bölme veya taşma gibi geçersiz işlemlerde özel durumlar oluşturan integral türlerine sahip işlemlerden farklı olarak özel durumlar oluşturmaz. Bunun yerine, bu durumlarda kayan nokta işleminin sonucu sıfır, pozitif sonsuz, negatif sonsuzdur veya sayı değildir (NaN):

  • Kayan nokta işleminin sonucu hedef biçim için çok küçükse, sonuç sıfır olur. Bu durum, aşağıdaki örnekte gösterildiği gibi çok küçük kayan noktalı iki sayı çarpıldığında ortaya çıkabilir.

    using System;
    
    public class Example6
    {
        public static void Main()
        {
            float value1 = 1.163287e-36f;
            float value2 = 9.164234e-25f;
            float result = value1 * value2;
            Console.WriteLine("{0} * {1} = {2}", value1, value2, result);
            Console.WriteLine("{0} = 0: {1}", result, result.Equals(0.0f));
        }
    }
    // The example displays the following output:
    //       1.163287E-36 * 9.164234E-25 = 0
    //       0 = 0: True
    
    let value1 = 1.163287e-36f
    let value2 = 9.164234e-25f
    let result = value1 * value2
    printfn $"{value1} * {value2} = {result}"
    printfn $"{result} = 0: {result.Equals(0f)}"
    // The example displays the following output:
    //       1.163287E-36 * 9.164234E-25 = 0
    //       0 = 0: True
    
    Module Example7
        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
    
  • Kayan nokta işleminin sonucunun büyüklüğü hedef biçimin aralığını aşarsa, işlemin PositiveInfinity sonucu sonucun işaretine uygun olarak veya NegativeInfinityolur. Taşan Single.MaxValue bir işlemin sonucu , PositiveInfinitytaşan Single.MinValue bir işlemin sonucu ise aşağıdaki örnekte gösterildiği gibi şeklindedir NegativeInfinity.

    using System;
    
    public class Example7
    {
        public static void Main()
        {
            float value1 = 3.065e35f;
            float value2 = 6.9375e32f;
            float result = value1 * value2;
            Console.WriteLine("PositiveInfinity: {0}",
                               Single.IsPositiveInfinity(result));
            Console.WriteLine("NegativeInfinity: {0}\n",
                              Single.IsNegativeInfinity(result));
    
            value1 = -value1;
            result = value1 * value2;
            Console.WriteLine("PositiveInfinity: {0}",
                               Single.IsPositiveInfinity(result));
            Console.WriteLine("NegativeInfinity: {0}",
                              Single.IsNegativeInfinity(result));
        }
    }
    
    // The example displays the following output:
    //       PositiveInfinity: True
    //       NegativeInfinity: False
    //       
    //       PositiveInfinity: False
    //       NegativeInfinity: True
    
    open System
    
    let value1 = 3.065e35f
    let value2 = 6.9375e32f
    let result = value1 * value2
    printfn $"PositiveInfinity: {Single.IsPositiveInfinity result}" 
    printfn $"NegativeInfinity: {Single.IsNegativeInfinity result}\n"
    
    let value3 = -value1
    let result2 = value3 * value2
    printfn $"PositiveInfinity: {Single.IsPositiveInfinity result}" 
    printfn $"NegativeInfinity: {Single.IsNegativeInfinity result}" 
    
    // The example displays the following output:
    //       PositiveInfinity: True
    //       NegativeInfinity: False
    //       
    //       PositiveInfinity: False
    //       NegativeInfinity: True
    
    Module Example8
        Public Sub Main()
            Dim value1 As Single = 3.065E+35
            Dim value2 As Single = 6.9375E+32
            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 ayrıca pozitif bir kar payı ile sıfıra bölmeden ve NegativeInfinity negatif bir kar payı ile sıfıra bölmeden elde edilen sonuçlar.

  • Kayan nokta işlemi geçersizse, işlemin sonucu olur NaN. Örneğin, NaN aşağıdaki işlemlerden elde edilen sonuçlar:

    • Sıfıra bölme ve sıfıra bölme. Sıfıra bölmenin diğer durumlarının veya NegativeInfinityile PositiveInfinity sonuçlandığını unutmayın.
    • Geçersiz giriş içeren herhangi bir kayan nokta işlemi. Örneğin, negatif bir değerin karekökünü bulmaya çalışmak döndürür NaN.
    • değeri Single.NaNolan bağımsız değişken içeren herhangi bir işlem.

Tür dönüştürmeleri

Yapı Single açık veya örtük dönüştürme işleçleri tanımlamaz; bunun yerine, dönüştürmeler derleyici tarafından uygulanır.

Aşağıdaki tabloda, diğer ilkel sayısal türlerin değerinin bir Single değere olası dönüştürmeleri listelenmiştir. Ayrıca, dönüştürmenin genişleyip daraltılmadığını ve sonuçta Single özgün değerden daha az duyarlık olup olmadığını gösterir.

Dönüştürme: Genişletme/daraltma Olası duyarlık kaybı
Byte Genişletme Hayır
Decimal Genişletme

C# için bir atama işleci gerektiğini unutmayın.
Evet. Decimal 29 ondalık duyarlık basamaklarını destekler; Single 9'i destekler.
Double Daralma; aralık dışı değerler veya Double.PositiveInfinitydeğerine Double.NegativeInfinity dönüştürülür. Evet. Double 17 ondalık duyarlık basamağı destekler; Single 9'i destekler.
Int16 Genişletme Hayır
Int32 Genişletme Evet. Int32 10 ondalık basamak duyarlık destekler; Single 9'i destekler.
Int64 Genişletme Evet. Int64 19 ondalık basamak duyarlık destekler; Single 9'i destekler.
SByte Genişletme Hayır
UInt16 Genişletme Hayır
UInt32 Genişletme Evet. UInt32 10 ondalık basamak duyarlık destekler; Single 9'i destekler.
UInt64 Genişletme Evet. Int64 20 ondalık basamak duyarlık destekler; Single 9'i destekler.

Aşağıdaki örnek, diğer ilkel sayısal türlerin en küçük veya en büyük değerini bir Single değere dönüştürür.

using System;

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

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

for value in values do
    let sngValue = 
        match value with
        | :? byte as v -> float32 v
        | :? decimal as v -> float32 v
        | :? double as v -> float32 v
        | :? int16 as v -> float32 v
        | :? int as v -> float32 v
        | :? int64 as v -> float32 v
        | :? int8 as v -> float32 v
        | :? uint16 as v -> float32 v
        | :? uint as v -> float32 v
        | :? uint64 as v -> float32 v
        | _ -> raise (NotImplementedException "Unknown Type")
    printfn $"{value} ({value.GetType().Name}) --> {sngValue:R} ({sngValue.GetType().Name})"
// The example displays the following output:
//       0 (Byte) --> 0 (Single)
//       255 (Byte) --> 255 (Single)
//       -79228162514264337593543950335 (Decimal) --> -7.92281625E+28 (Single)
//       79228162514264337593543950335 (Decimal) --> 7.92281625E+28 (Single)
//       -1.79769313486232E+308 (Double) --> -Infinity (Single)
//       1.79769313486232E+308 (Double) --> Infinity (Single)
//       -32768 (Int16) --> -32768 (Single)
//       32767 (Int16) --> 32767 (Single)
//       -2147483648 (Int32) --> -2.14748365E+09 (Single)
//       2147483647 (Int32) --> 2.14748365E+09 (Single)
//       -9223372036854775808 (Int64) --> -9.223372E+18 (Single)
//       9223372036854775807 (Int64) --> 9.223372E+18 (Single)
//       -128 (SByte) --> -128 (Single)
//       127 (SByte) --> 127 (Single)
//       0 (UInt16) --> 0 (Single)
//       65535 (UInt16) --> 65535 (Single)
//       0 (UInt32) --> 0 (Single)
//       4294967295 (UInt32) --> 4.2949673E+09 (Single)
//       0 (UInt64) --> 0 (Single)
//       18446744073709551615 (UInt64) --> 1.84467441E+19 (Single)
Module Example5
    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)

Buna ek olarak, Double , ve Double.NegativeInfinity değerleri Double.PositiveInfinityDouble.NaNsırasıyla , Single.PositiveInfinityve Single.NegativeInfinityolarak dönüştürülürSingle.NaN.

Bazı sayısal türlerin değerini bir değere Single dönüştürme işleminin duyarlık kaybı içerebileceğini unutmayın. Örnekte gösterildiği gibi, , , Double, Int64Int32, UInt32ve UInt64 değerlerini değerlere Single dönüştürürken Decimalduyarlık kaybı mümkündür.

Bir Single değerin bir değerine dönüştürülmesi Double , genişleten bir dönüştürmedir. Türün değer için kesin bir gösterimi yoksa Double dönüştürme duyarlık kaybına Single neden olabilir.

Değerin Single , bir dışında Double herhangi bir ilkel sayısal veri türünün değerine dönüştürülmesi bir daraltma dönüştürmesidir ve bir atama işleci (C#'de) veya dönüştürme yöntemi (Visual Basic'te) gerektirir. Hedef türün ve MaxValue özellikleri tarafından tanımlanan hedef veri türü aralığının MinValue dışında olan değerler, aşağıdaki tabloda gösterildiği gibi davranır.

Hedef türü Result
Herhangi bir tam sayı türü OverflowException Dönüştürmenin denetlenen bir bağlamda gerçekleşmesi durumunda bir özel durum.

Dönüştürme işaretlenmemiş bir bağlamda gerçekleşirse (C# dilinde varsayılan değer), dönüştürme işlemi başarılı olur ancak değer taşıyor.
Decimal Bir OverflowException özel durum,

Buna ek olarak, Single.NaN, Single.PositiveInfinityve Single.NegativeInfinity işaretli bir bağlamda tamsayılara dönüştürmeler için bir oluşturur OverflowException , ancak bu değerler işaretsiz bir bağlamda tamsayılara dönüştürüldüğünde taşıyor. dönüştürmeleri Decimaliçin her zaman bir OverflowExceptionoluşturur. dönüştürmeleri Doubleiçin sırasıyla , Double.PositiveInfinityve Double.NegativeInfinityolarak dönüştürülürDouble.NaN.

Duyarlık kaybı, değerin başka bir Single sayısal türe dönüştürülmesinden kaynaklanabilir. Tam sayı Single olmayan değerlerin dönüştürülmesi durumunda, örnekte gösterilen çıktıda gösterildiği gibi, değer yuvarlandığında Single (Visual Basic'te olduğu gibi) veya kesildiğinde (C# ve F# dilinde olduğu gibi) kesirli bileşen kaybolur. Değerlere dönüştürmeler için Decimal , değerin Single hedef veri türünde kesin bir gösterimi olmayabilir.

Aşağıdaki örnek, bir dizi Single değeri diğer birkaç sayısal türe dönüştürür. Dönüştürmeler Visual Basic'te (varsayılan), C# dilinde (işaretli anahtar sözcük nedeniyle) ve F# dilinde (deyimi nedeniyleopen Checked) denetlenen bir bağlamda gerçekleşir. Örnekten elde edilen çıktı, işaretlenmemiş bir bağlamın her ikisinde de dönüştürmelerin sonucunu gösterir. Visual Basic'te derleyici anahtarıyla /removeintchecks+ derleyerek, C# dilinde deyimini açıklama satırı yaparak ve F# dilinde deyimini açıklama satırı yaparak denetlenmeyen checkedopen Checked bir bağlamda dönüştürme gerçekleştirebilirsiniz.

using System;

public class Example5
{
    public static void Main()
    {
        float[] values = { Single.MinValue, -67890.1234f, -12345.6789f,
                         12345.6789f, 67890.1234f, Single.MaxValue,
                         Single.NaN, Single.PositiveInfinity,
                         Single.NegativeInfinity };
        checked
        {
            foreach (var value in values)
            {
                try
                {
                    Int64 lValue = (long)value;
                    Console.WriteLine("{0} ({1}) --> {2} (0x{2:X16}) ({3})",
                                      value, value.GetType().Name,
                                      lValue, lValue.GetType().Name);
                }
                catch (OverflowException)
                {
                    Console.WriteLine("Unable to convert {0} to Int64.", value);
                }
                try
                {
                    UInt64 ulValue = (ulong)value;
                    Console.WriteLine("{0} ({1}) --> {2} (0x{2:X16}) ({3})",
                                      value, value.GetType().Name,
                                      ulValue, ulValue.GetType().Name);
                }
                catch (OverflowException)
                {
                    Console.WriteLine("Unable to convert {0} to UInt64.", value);
                }
                try
                {
                    Decimal dValue = (decimal)value;
                    Console.WriteLine("{0} ({1}) --> {2} ({3})",
                                      value, value.GetType().Name,
                                      dValue, dValue.GetType().Name);
                }
                catch (OverflowException)
                {
                    Console.WriteLine("Unable to convert {0} to Decimal.", value);
                }

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

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

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

    let dblValue = double value
    printfn $"{value} ({value.GetType().Name}) --> {dblValue} ({dblValue.GetType().Name})\n"
// The example displays the following output for conversions performed
// in a checked context:
//       Unable to convert -3.402823E+38 to Int64.
//       Unable to convert -3.402823E+38 to UInt64.
//       Unable to convert -3.402823E+38 to Decimal.
//       -3.402823E+38 (Single) --> -3.40282346638529E+38 (Double)
//
//       -67890.13 (Single) --> -67890 (0xFFFFFFFFFFFEF6CE) (Int64)
//       Unable to convert -67890.13 to UInt64.
//       -67890.13 (Single) --> -67890.12 (Decimal)
//       -67890.13 (Single) --> -67890.125 (Double)
//
//       -12345.68 (Single) --> -12345 (0xFFFFFFFFFFFFCFC7) (Int64)
//       Unable to convert -12345.68 to UInt64.
//       -12345.68 (Single) --> -12345.68 (Decimal)
//       -12345.68 (Single) --> -12345.6787109375 (Double)
//
//       12345.68 (Single) --> 12345 (0x0000000000003039) (Int64)
//       12345.68 (Single) --> 12345 (0x0000000000003039) (UInt64)
//       12345.68 (Single) --> 12345.68 (Decimal)
//       12345.68 (Single) --> 12345.6787109375 (Double)
//
//       67890.13 (Single) --> 67890 (0x0000000000010932) (Int64)
//       67890.13 (Single) --> 67890 (0x0000000000010932) (UInt64)
//       67890.13 (Single) --> 67890.12 (Decimal)
//       67890.13 (Single) --> 67890.125 (Double)
//
//       Unable to convert 3.402823E+38 to Int64.
//       Unable to convert 3.402823E+38 to UInt64.
//       Unable to convert 3.402823E+38 to Decimal.
//       3.402823E+38 (Single) --> 3.40282346638529E+38 (Double)
//
//       Unable to convert NaN to Int64.
//       Unable to convert NaN to UInt64.
//       Unable to convert NaN to Decimal.
//       NaN (Single) --> NaN (Double)
//
//       Unable to convert Infinity to Int64.
//       Unable to convert Infinity to UInt64.
//       Unable to convert Infinity to Decimal.
//       Infinity (Single) --> Infinity (Double)
//
//       Unable to convert -Infinity to Int64.
//       Unable to convert -Infinity to UInt64.
//       Unable to convert -Infinity to Decimal.
//       -Infinity (Single) --> -Infinity (Double)
// The example displays the following output for conversions performed
// in an unchecked context:
//       -3.402823E+38 (Single) --> -9223372036854775808 (0x8000000000000000) (Int64)
//       -3.402823E+38 (Single) --> 9223372036854775808 (0x8000000000000000) (UInt64)
//       Unable to convert -3.402823E+38 to Decimal.
//       -3.402823E+38 (Single) --> -3.40282346638529E+38 (Double)
//
//       -67890.13 (Single) --> -67890 (0xFFFFFFFFFFFEF6CE) (Int64)
//       -67890.13 (Single) --> 18446744073709483726 (0xFFFFFFFFFFFEF6CE) (UInt64)
//       -67890.13 (Single) --> -67890.12 (Decimal)
//       -67890.13 (Single) --> -67890.125 (Double)
//
//       -12345.68 (Single) --> -12345 (0xFFFFFFFFFFFFCFC7) (Int64)
//       -12345.68 (Single) --> 18446744073709539271 (0xFFFFFFFFFFFFCFC7) (UInt64)
//       -12345.68 (Single) --> -12345.68 (Decimal)
//       -12345.68 (Single) --> -12345.6787109375 (Double)
//
//       12345.68 (Single) --> 12345 (0x0000000000003039) (Int64)
//       12345.68 (Single) --> 12345 (0x0000000000003039) (UInt64)
//       12345.68 (Single) --> 12345.68 (Decimal)
//       12345.68 (Single) --> 12345.6787109375 (Double)
//
//       67890.13 (Single) --> 67890 (0x0000000000010932) (Int64)
//       67890.13 (Single) --> 67890 (0x0000000000010932) (UInt64)
//       67890.13 (Single) --> 67890.12 (Decimal)
//       67890.13 (Single) --> 67890.125 (Double)
//
//       3.402823E+38 (Single) --> -9223372036854775808 (0x8000000000000000) (Int64)
//       3.402823E+38 (Single) --> 0 (0x0000000000000000) (UInt64)
//       Unable to convert 3.402823E+38 to Decimal.
//       3.402823E+38 (Single) --> 3.40282346638529E+38 (Double)
//
//       NaN (Single) --> -9223372036854775808 (0x8000000000000000) (Int64)
//       NaN (Single) --> 0 (0x0000000000000000) (UInt64)
//       Unable to convert NaN to Decimal.
//       NaN (Single) --> NaN (Double)
//
//       Infinity (Single) --> -9223372036854775808 (0x8000000000000000) (Int64)
//       Infinity (Single) --> 0 (0x0000000000000000) (UInt64)
//       Unable to convert Infinity to Decimal.
//       Infinity (Single) --> Infinity (Double)
//
//       -Infinity (Single) --> -9223372036854775808 (0x8000000000000000) (Int64)
//       -Infinity (Single) --> 9223372036854775808 (0x8000000000000000) (UInt64)
//       Unable to convert -Infinity to Decimal.
//       -Infinity (Single) --> -Infinity (Double)
Module Example6
    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)

Sayısal türlerin dönüştürülmesi hakkında daha fazla bilgi için bkz . .NET'te Tür Dönüştürme ve Tür Dönüştürme Tabloları.

Kayan nokta işlevleri

Yapı Single ve ilgili türler aşağıdaki işlem kategorilerini gerçekleştirmek için yöntemler sağlar:

  • Değerlerin karşılaştırması. İki değerin Equals eşit olup olmadığını belirlemek için yöntemini veya CompareTo iki Single değer arasındaki ilişkiyi belirlemek için yöntemini çağırabilirsiniz.

    Yapısı Single , tam bir karşılaştırma işleçleri kümesini de destekler. Örneğin, eşitliği veya eşitsizliği test edebilir veya bir değerin başka bir değerden büyük mü yoksa başka bir değere eşit mi olduğunu belirleyebilirsiniz. İşlenenlerden biri bir DoubleSingle ise, değer karşılaştırma gerçekleştirilmeden önce değerine Double dönüştürülür. İşlenenlerden biri tam sayı türündeyse, karşılaştırma gerçekleştirilmeden önce değerine Single dönüştürülür. Bunlar genişletme dönüştürmeleri olsa da, duyarlık kaybı içerebilir.

    Uyarı

    Duyarlık farklılıkları nedeniyle, eşit olmasını beklediğiniz iki Single değerin eşit olmadığı ortaya çıkabilir ve bu da karşılaştırmanın sonucunu etkiler. İki Single değeri karşılaştırma hakkında daha fazla bilgi için Eşitlik testi bölümüne bakın.

    Ayrıca, bu özel değerleri test etmek için , IsInfinity, IsPositiveInfinityve IsNegativeInfinity yöntemlerini çağırabilirsinizIsNaN.

  • Matematiksel işlemler. Toplama, çıkarma, çarpma ve bölme gibi yaygın aritmetik işlemler yöntemler yerine dil derleyicileri ve Ortak Ara Dil (CIL) yönergeleri tarafından Single uygulanır. Matematiksel işlemdeki diğer işlenen bir Doubleise, Single işlemi gerçekleştirmeden önce öğesine dönüştürülür Double ve işlemin sonucu da bir Double değerdir. Diğer işlenen tam sayı türündeyse, işlemi gerçekleştirmeden önce a'ya Single dönüştürülür ve işlemin sonucu da bir Single değerdir.

    Sınıfındaki (Shared Visual Basic'te) yöntemlerini System.Math çağırarak static diğer matematiksel işlemleri gerçekleştirebilirsiniz. Bunlar aritmetik (, , ve gibiMath.Abs), geometri (ve gibi Math.CosMath.Sin) ve hesap (gibiMath.Log) için yaygın olarak kullanılan ek yöntemleri içerir. Math.SignMath.Sqrt Her durumda, Single değer değerine Doubledönüştürülür.

    Ayrıca, bir Single değerdeki tek tek bitleri de işleyebilirsiniz. yöntemi bit BitConverter.GetBytes(Single) desenini bayt dizisinde döndürür. Bu bayt dizisini yöntemine BitConverter.ToInt32 geçirerek, değerin bit desenini Single 32 bitlik bir tamsayıda da koruyabilirsiniz.

  • Yuvarlama. Yuvarlama genellikle kayan nokta gösterimi ve duyarlık sorunlarının neden olduğu değerler arasındaki farkların etkisini azaltmak için bir teknik olarak kullanılır. yöntemini çağırarak Math.Round bir Single değeri yuvarlayabilirsiniz. Ancak, yöntemi çağrılmadan önce değerin a'ya Double dönüştürüldüğünü ve dönüştürmenin duyarlık kaybı içerebileceğini unutmayınSingle.

  • Biçimlendirme. Yöntemini çağırarak ToString veya bileşik biçimlendirme özelliğini kullanarak bir Single değeri dize gösterimine dönüştürebilirsiniz. Biçim dizelerinin kayan nokta değerlerinin dize gösterimini nasıl denetlediğini öğrenmek için Standart Sayısal Biçim Dizeleri ve Özel Sayısal Biçim Dizeleri konularına bakın.

  • Dizeleri ayrıştırma. veya TryParse yöntemini çağırarak kayan nokta değerinin dize gösterimini bir Single değere Parse dönüştürebilirsiniz. Ayrıştırma işlemi başarısız olursa yöntemi Parse bir özel durum oluştururken TryParse yöntemi döndürür false.

  • Tür dönüştürme. yapısı Single , arabirim için iki standart .NET veri türü arasında dönüştürmeyi IConvertible destekleyen açık bir arabirim uygulaması sağlar. Dil derleyicileri, değerlerin değerlere dönüştürülmesi dışında diğer tüm standart sayısal türler için değerlerin Double örtük olarak dönüştürülmesi de Single desteklenir. dışında herhangi bir standart sayısal türdeki Double bir değerin bir değerine dönüştürülmesi Single bir genişletme dönüştürmesidir ve bir atama işlecinin veya dönüştürme yönteminin kullanılmasını gerektirmez.

    Ancak, 32 bit ve 64 bit tamsayı değerlerinin dönüştürülmesi duyarlık kaybı içerebilir. Aşağıdaki tabloda 32 bit, 64 bit ve Double türler için duyarlık farklılıkları listelenmiştir:

    Tür En yüksek duyarlık (ondalık basamaklarda) İç duyarlık (ondalık basamaklarda)
    Double 15 17
    Int32 ve UInt32 10 10
    Int64 ve UInt64 19 19
    Single 7 9

    Duyarlık sorunu en sık değerlere Double dönüştürülen değerleri etkilerSingle. Aşağıdaki örnekte, aynı bölme işlemleri tarafından üretilen iki değer eşit değildir, çünkü değerlerden biri değerine dönüştürülmüş Doubletek duyarlıklı kayan nokta değeridir.

    using System;
    
    public class Example8
    {
        public static void Main()
        {
            Double value1 = 1 / 3.0;
            Single sValue2 = 1 / 3.0f;
            Double value2 = (Double)sValue2;
            Console.WriteLine("{0:R} = {1:R}: {2}", value1, value2,
                                                value1.Equals(value2));
        }
    }
    // The example displays the following output:
    //        0.33333333333333331 = 0.3333333432674408: False
    
    let value1 = 1. / 3.
    let sValue2 = 1f / 3f
    let value2 = double sValue2
    printfn $"{value1:R} = {value2:R}: {value1.Equals value2}"
    // The example displays the following output:
    //        0.33333333333333331 = 0.3333333432674408: False
    
    Module Example9
        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