Struktur System.Double

Artikel ini menyediakan keterangan tambahan untuk dokumentasi referensi untuk API ini.

Double Jenis nilai mewakili angka 64-bit presisi ganda dengan nilai mulai dari negatif 1,79769313486232e308 hingga positif 1,79769313486232e308, serta nol positif atau negatif, PositiveInfinity, NegativeInfinity, dan bukan angka (NaN). Ini dimaksudkan untuk mewakili nilai-nilai yang sangat besar (seperti jarak antara planet atau galaksi) atau sangat kecil (seperti massa molekul zat dalam kilogram) dan yang sering tidak tepat (seperti jarak dari bumi ke tata surya lain). Jenis ini Double sesuai dengan standar IEC 60559:1989 (IEEE 754) untuk aritmatika floating-point biner.

Representasi dan presisi titik mengambang

Jenis Double data menyimpan nilai floating-point presisi ganda dalam format biner 64-bit, seperti yang diperlihatkan dalam tabel berikut:

Bagian Bit
Significand atau mantissa 0-51
Eksponen 52-62
Tanda (0 = Positif, 1 = Negatif) 63

Sama seperti pecahan desimal tidak dapat secara tepat mewakili beberapa nilai pecahan (seperti 1/3 atau Math.PI), pecahan biner tidak dapat mewakili beberapa nilai pecahan. Misalnya, 1/10, yang diwakili dengan tepat oleh .1 sebagai pecahan desimal, diwakili oleh .001100110011 sebagai pecahan biner, dengan pola "0011" berulang ke tak terbatas. Dalam hal ini, nilai floating-point memberikan representasi angka yang tidak tepat yang diwakilinya. Melakukan operasi matematika tambahan pada nilai floating-point asli sering cenderung meningkatkan kurangnya presisinya. Misalnya, jika kita membandingkan hasil mengalikan .1 dengan 10 dan menambahkan .1 ke .1 sembilan kali, kita melihat penambahan itu, karena telah melibatkan delapan operasi lagi, telah menghasilkan hasil yang kurang tepat. Perhatikan bahwa perbedaan ini hanya jelas jika kita menampilkan dua Double nilai dengan menggunakan string format numerik standar "R", yang jika perlu menampilkan semua 17 digit presisi yang didukung oleh jenis .Double

using System;

public class Example13
{
    public static void Main()
    {
        Double value = .1;
        Double result1 = value * 10;
        Double result2 = 0;
        for (int ctr = 1; ctr <= 10; ctr++)
            result2 += value;

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

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

Karena beberapa angka tidak dapat direpresentasikan persis sebagai nilai biner pecahan, angka floating-point hanya dapat memperhitungkan angka riil.

Semua angka floating-point juga memiliki jumlah digit signifikan yang terbatas, yang juga menentukan seberapa akurat nilai floating-point perkiraan angka riil. Nilai Double memiliki hingga 15 digit desimal presisi, meskipun maksimum 17 digit dipertahankan secara internal. Ini berarti bahwa beberapa operasi floating-point mungkin tidak memiliki presisi untuk mengubah nilai titik mengambang. Contoh berikut memberikan ilustrasi. Ini mendefinisikan nilai floating-point yang sangat besar, dan kemudian menambahkan produk dan Double.Epsilon satu quadrillion ke dalamnya. Namun, produk ini terlalu kecil untuk memodifikasi nilai floating-point asli. Digit yang paling tidak signifikan adalah seribu, sedangkan digit paling signifikan dalam produk adalah 10-309.

using System;

public class Example14
{
    public static void Main()
    {
        Double value = 123456789012.34567;
        Double additional = Double.Epsilon * 1e15;
        Console.WriteLine("{0} + {1} = {2}", value, additional,
                                             value + additional);
    }
}
// The example displays the following output:
//    123456789012.346 + 4.94065645841247E-309 = 123456789012.346
open System

let value = 123456789012.34567
let additional = Double.Epsilon * 1e15
printfn $"{value} + {additional} = {value + additional}"
// The example displays the following output:
//    123456789012.346 + 4.94065645841247E-309 = 123456789012.346
Module Example15
    Public Sub Main()
        Dim value As Double = 123456789012.34567
        Dim additional As Double = Double.Epsilon * 1.0E+15
        Console.WriteLine("{0} + {1} = {2}", value, additional,
                                           value + additional)
    End Sub
End Module
' The example displays the following output:
'   123456789012.346 + 4.94065645841247E-309 = 123456789012.346

Presisi terbatas dari angka floating-point memiliki beberapa konsekuensi:

  • Dua angka floating-point yang tampak sama untuk presisi tertentu mungkin tidak dibandingkan sama karena digit yang paling tidak signifikan berbeda. Dalam contoh berikut, serangkaian angka ditambahkan bersama-sama, dan totalnya dibandingkan dengan total yang diharapkan. Meskipun kedua nilai tampaknya sama, panggilan ke metode menunjukkan bahwa nilai tersebut Equals tidak.

    using System;
    
    public class Example10
    {
        public static void Main()
        {
            Double[] values = { 10.0, 2.88, 2.88, 2.88, 9.0 };
            Double result = 27.64;
            Double total = 0;
            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 (36.64) does not equal the total (36.64).
    //
    // 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).
    
    let values = [ 10.0; 2.88; 2.88; 2.88; 9.0 ]
    let result = 27.64
    let total = List.sum values
    
    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 (36.64) does not equal the total (36.64).
    //
    // 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).
    
    Module Example11
        Public Sub Main()
            Dim values() As Double = {10.0, 2.88, 2.88, 2.88, 9.0}
            Dim result As Double = 27.64
            Dim total As Double
            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 (36.64) does not equal the total (36.64).   
    '
    ' 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).
    

    Jika Anda mengubah item format dalam Console.WriteLine(String, Object, Object) pernyataan dari {0} dan {1} ke {0:R} dan {1:R} untuk menampilkan semua digit signifikan dari dua Double nilai, jelas bahwa kedua nilai tersebut tidak sama karena hilangnya presisi selama operasi penambahan. Dalam hal ini, masalah dapat diselesaikan dengan memanggil metode untuk membulatkan Math.Round(Double, Int32)Double nilai ke presisi yang diinginkan sebelum melakukan perbandingan.

  • Operasi matematika atau perbandingan yang menggunakan angka floating-point mungkin tidak menghasilkan hasil yang sama jika angka desimal digunakan, karena angka floating-point biner mungkin tidak sama dengan angka desimal. Contoh sebelumnya mengilustrasikan ini dengan menampilkan hasil mengalikan .1 dengan 10 dan menambahkan .1 kali.

    Ketika akurasi dalam operasi numerik dengan nilai pecahan penting, Anda dapat menggunakan Decimal bukan jenisnya Double . Ketika akurasi dalam operasi numerik dengan nilai integral di luar rentang Int64 atau UInt64 jenis penting, gunakan jenis .BigInteger

  • Nilai mungkin tidak melakukan round-trip jika nomor floating-point terlibat. Nilai dikatakan untuk round-trip jika operasi mengonversi angka floating-point asli ke bentuk lain, operasi terbalik mengubah formulir yang dikonversi kembali ke angka floating-point, dan angka floating-point akhir tidak sama dengan angka floating-point asli. Perjalanan pulang pergi mungkin gagal karena satu atau beberapa digit yang paling tidak signifikan hilang atau diubah dalam konversi. Dalam contoh berikut, tiga Double nilai dikonversi menjadi string dan disimpan dalam file. Namun, seperti yang ditunjukkan oleh output, meskipun nilainya tampak identik, nilai yang dipulihkan tidak sama dengan nilai asli.

    using System;
    using System.IO;
    
    public class Example11
    {
        public static void Main()
        {
            StreamWriter sw = new StreamWriter(@".\Doubles.dat");
            Double[] values = { 2.2 / 1.01, 1.0 / 3, Math.PI };
            for (int ctr = 0; ctr < values.Length; ctr++)
            {
                sw.Write(values[ctr].ToString());
                if (ctr != values.Length - 1)
                    sw.Write("|");
            }
            sw.Close();
    
            Double[] restoredValues = new Double[values.Length];
            StreamReader sr = new StreamReader(@".\Doubles.dat");
            string temp = sr.ReadToEnd();
            string[] tempStrings = temp.Split('|');
            for (int ctr = 0; ctr < tempStrings.Length; ctr++)
                restoredValues[ctr] = Double.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.17821782178218 <> 2.17821782178218
    //       0.333333333333333 <> 0.333333333333333
    //       3.14159265358979 <> 3.14159265358979
    
    open System
    open System.IO
    
    let values = [ 2.2 / 1.01; 1. / 3.; Math.PI ]
    
    using (new StreamWriter(@".\Doubles.dat")) (fun sw ->
        for i = 0 to values.Length - 1 do
            sw.Write(string values[i])
            if i <> values.Length - 1 then
                sw.Write "|")
    
    using (new StreamReader(@".\Doubles.dat")) (fun sr ->
        let temp = sr.ReadToEnd()
        let tempStrings = temp.Split '|'
    
        let restoredValues =
            [ for i = 0 to tempStrings.Length - 1 do
                  Double.Parse tempStrings[i] ]
    
        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.17821782178218 <> 2.17821782178218
    //       0.333333333333333 <> 0.333333333333333
    //       3.14159265358979 <> 3.14159265358979
    
    Imports System.IO
    
    Module Example12
        Public Sub Main()
            Dim sw As New StreamWriter(".\Doubles.dat")
            Dim values() As Double = {2.2 / 1.01, 1.0 / 3, 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 Double
            Dim sr As New StreamReader(".\Doubles.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) = Double.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.17821782178218 <> 2.17821782178218
    '       0.333333333333333 <> 0.333333333333333
    '       3.14159265358979 <> 3.14159265358979
    

    Dalam hal ini, nilai dapat berhasil disandingkan dengan menggunakan string format numerik standar "G17" untuk mempertahankan presisi Double penuh nilai, seperti yang ditunjukkan contoh berikut.

    using System;
    using System.IO;
    
    public class Example12
    {
        public static void Main()
        {
            StreamWriter sw = new StreamWriter(@".\Doubles.dat");
            Double[] values = { 2.2 / 1.01, 1.0 / 3, Math.PI };
            for (int ctr = 0; ctr < values.Length; ctr++)
                sw.Write("{0:G17}{1}", values[ctr], ctr < values.Length - 1 ? "|" : "");
    
            sw.Close();
    
            Double[] restoredValues = new Double[values.Length];
            StreamReader sr = new StreamReader(@".\Doubles.dat");
            string temp = sr.ReadToEnd();
            string[] tempStrings = temp.Split('|');
            for (int ctr = 0; ctr < tempStrings.Length; ctr++)
                restoredValues[ctr] = Double.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.17821782178218 = 2.17821782178218
    //       0.333333333333333 = 0.333333333333333
    //       3.14159265358979 = 3.14159265358979
    
    open System
    open System.IO
    
    let values = [ 2.2 / 1.01; 1. / 3.; Math.PI ]
    
    using (new StreamWriter(@".\Doubles.dat")) (fun sw -> 
        for i = 0 to values.Length - 1 do
            sw.Write $"""{values[i]:G17}{if i < values.Length - 1 then "|" else ""}""")
    
    using (new StreamReader(@".\Doubles.dat")) (fun sr ->
        let temp = sr.ReadToEnd()
        let tempStrings = temp.Split '|'
        
        let restoredValues = 
          [ for i = 0 to tempStrings.Length - 1 do
                Double.Parse tempStrings[i] ]
    
        for i = 0 to values.Length - 1 do
            printfn $"""{restoredValues[i]} {if values[i].Equals restoredValues[i] then "=" else "<>"} {values[i]}""")
    
    // The example displays the following output:
    //       2.17821782178218 = 2.17821782178218
    //       0.333333333333333 = 0.333333333333333
    //       3.14159265358979 = 3.14159265358979
    
    Imports System.IO
    
    Module Example13
        Public Sub Main()
            Dim sw As New StreamWriter(".\Doubles.dat")
            Dim values() As Double = {2.2 / 1.01, 1.0 / 3, Math.PI}
            For ctr As Integer = 0 To values.Length - 1
                sw.Write("{0:G17}{1}", values(ctr),
                      If(ctr < values.Length - 1, "|", ""))
            Next
            sw.Close()
    
            Dim restoredValues(values.Length - 1) As Double
            Dim sr As New StreamReader(".\Doubles.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) = Double.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.17821782178218 = 2.17821782178218
    '       0.333333333333333 = 0.333333333333333
    '       3.14159265358979 = 3.14159265358979
    

    Penting

    Saat digunakan dengan Double nilai, penentu format "R" dalam beberapa kasus gagal melakukan pulang pergi nilai asli. Untuk memastikan bahwa Double nilai berhasil pulang pergi, gunakan penentu format "G17".

  • Single nilai memiliki presisi yang lebih sedikit daripada Double nilai. Nilai Single yang dikonversi ke yang tampaknya setara Double sering kali tidak sama dengan Double nilai karena perbedaan presisi. Dalam contoh berikut, hasil operasi pembagian yang identik ditetapkan ke nilai Double dan Single . Setelah nilai dilemparkan Single ke Double, perbandingan dari dua nilai menunjukkan bahwa nilai tersebut tidak sama.

    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
    

    Untuk menghindari masalah ini, gunakan Double sebagai pengganti Single jenis data, atau gunakan Round metode sehingga kedua nilai memiliki presisi yang sama.

Selain itu, hasil operasi aritmatika dan penugasan dengan Double nilai mungkin sedikit berbeda berdasarkan platform karena hilangnya presisi jenis.Double Misalnya, hasil penetapan nilai harfiah Double mungkin berbeda dalam versi .NET 32-bit dan 64-bit. Contoh berikut menggambarkan perbedaan ini ketika nilai harfiah -4.42330604244772E-305 dan variabel yang nilainya adalah -4.42330604244772E-305 ditetapkan ke Double variabel. Perhatikan bahwa hasil Parse(String) metode dalam hal ini tidak menderita hilangnya presisi.

double value = -4.42330604244772E-305;

double fromLiteral = -4.42330604244772E-305;
double fromVariable = value;
double fromParse = Double.Parse("-4.42330604244772E-305");

Console.WriteLine("Double value from literal: {0,29:R}", fromLiteral);
Console.WriteLine("Double value from variable: {0,28:R}", fromVariable);
Console.WriteLine("Double value from Parse method: {0,24:R}", fromParse);
// On 32-bit versions of the .NET Framework, the output is:
//    Double value from literal:        -4.42330604244772E-305
//    Double value from variable:       -4.42330604244772E-305
//    Double value from Parse method:   -4.42330604244772E-305
//
// On other versions of the .NET Framework, the output is:
//    Double value from literal:      -4.4233060424477198E-305
//    Double value from variable:     -4.4233060424477198E-305
//    Double value from Parse method:   -4.42330604244772E-305
let value = -4.42330604244772E-305

let fromLiteral = -4.42330604244772E-305
let fromVariable = value
let fromParse = Double.Parse "-4.42330604244772E-305"

printfn $"Double value from literal: {fromLiteral,29:R}"
printfn $"Double value from variable: {fromVariable,28:R}"
printfn $"Double value from Parse method: {fromParse,24:R}"
// On 32-bit versions of the .NET Framework, the output is:
//    Double value from literal:        -4.42330604244772E-305
//    Double value from variable:       -4.42330604244772E-305
//    Double value from Parse method:   -4.42330604244772E-305
//
// On other versions of the .NET Framework, the output is:
//    Double value from literal:      -4.4233060424477198E-305
//    Double value from variable:     -4.4233060424477198E-305
//    Double value from Parse method:   -4.42330604244772E-305
Dim value As Double = -4.4233060424477198E-305

Dim fromLiteral As Double = -4.4233060424477198E-305
Dim fromVariable As Double = value
Dim fromParse As Double = Double.Parse("-4.42330604244772E-305")

Console.WriteLine("Double value from literal: {0,29:R}", fromLiteral)
Console.WriteLine("Double value from variable: {0,28:R}", fromVariable)
Console.WriteLine("Double value from Parse method: {0,24:R}", fromParse)
' On 32-bit versions of the .NET Framework, the output is:
'    Double value from literal:        -4.42330604244772E-305
'    Double value from variable:       -4.42330604244772E-305
'    Double value from Parse method:   -4.42330604244772E-305
'
' On other versions of the .NET Framework, the output is:
'    Double value from literal:        -4.4233060424477198E-305
'    Double value from variable:       -4.4233060424477198E-305
'    Double value from Parse method:     -4.42330604244772E-305

Uji kesetaraan

Agar dianggap sama, dua Double nilai harus mewakili nilai yang identik. Namun, karena perbedaan presisi antara nilai, atau karena hilangnya presisi oleh satu atau kedua nilai, nilai floating-point yang diharapkan identik sering kali berubah menjadi tidak sama karena perbedaan digit yang paling tidak signifikan. Akibatnya, memanggil ke Equals metode untuk menentukan apakah dua nilai sama, atau memanggil ke CompareTo metode untuk menentukan hubungan antara dua Double nilai, sering kali menghasilkan hasil yang tidak terduga. Ini terbukti dalam contoh berikut, di mana dua nilai yang tampaknya sama Double ternyata tidak sama karena yang pertama memiliki presisi 15 digit, sedangkan yang kedua memiliki 17.

using System;

public class Example
{
   public static void Main()
   {
      double value1 = .333333333333333;
      double value2 = 1.0/3;
      Console.WriteLine("{0:R} = {1:R}: {2}", value1, value2, value1.Equals(value2));
   }
}
// The example displays the following output:
//        0.333333333333333 = 0.33333333333333331: False
open System

let value1 = 0.333333333333333
let value2 = 1. / 3.
printfn $"{value1:R} = {value2:R}: {value1.Equals value2}"
// The example displays the following output:
//        0.333333333333333 = 0.33333333333333331: False
Module Example1
    Public Sub Main()
        Dim value1 As Double = 0.333333333333333
        Dim value2 As Double = 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.333333333333333 = 0.33333333333333331: False

Nilai terhitung yang mengikuti jalur kode yang berbeda dan yang dimanipulasi dengan cara yang berbeda sering terbukti tidak sama. Dalam contoh berikut, satu Double nilai dikuadratkan, lalu akar kuadrat dihitung untuk memulihkan nilai asli. Double Detik dikalikan dengan 3,51 dan kuadrat sebelum akar kuadrat hasil dibagi 3,51 untuk memulihkan nilai asli. Meskipun kedua nilai tampaknya identik, panggilan ke metode menunjukkan bahwa nilai tersebut Equals(Double) tidak sama. Menggunakan string format standar "R" untuk mengembalikan string hasil yang menampilkan semua digit signifikan dari setiap nilai Ganda menunjukkan bahwa nilai kedua adalah .0000000000001 kurang dari yang pertama.

using System;

public class Example1
{
    public static void Main()
    {
        double value1 = 100.10142;
        value1 = Math.Sqrt(Math.Pow(value1, 2));
        double value2 = Math.Pow(value1 * 3.51, 2);
        value2 = Math.Sqrt(value2) / 3.51;
        Console.WriteLine("{0} = {1}: {2}\n",
                          value1, value2, value1.Equals(value2));
        Console.WriteLine("{0:R} = {1:R}", value1, value2);
    }
}
// The example displays the following output:
//    100.10142 = 100.10142: False
//
//    100.10142 = 100.10141999999999
open System

let value1 = 
    Math.Pow(100.10142, 2)
    |> sqrt

let value2 = 
    let v = pown (value1 * 3.51) 2
    (Math.Sqrt v) / 3.51

printfn $"{value1} = {value2}: {value1.Equals value2}\n"
printfn $"{value1:R} = {value2:R}"
// The example displays the following output:
//    100.10142 = 100.10142: False
//
//    100.10142 = 100.10141999999999
Module Example2
    Public Sub Main()
        Dim value1 As Double = 100.10142
        value1 = Math.Sqrt(Math.Pow(value1, 2))
        Dim value2 As Double = Math.Pow(value1 * 3.51, 2)
        value2 = Math.Sqrt(value2) / 3.51
        Console.WriteLine("{0} = {1}: {2}",
                        value1, value2, value1.Equals(value2))
        Console.WriteLine()
        Console.WriteLine("{0:R} = {1:R}", value1, value2)
    End Sub
End Module
' The example displays the following output:
'    100.10142 = 100.10142: False
'    
'    100.10142 = 100.10141999999999

Dalam kasus di mana hilangnya presisi kemungkinan akan memengaruhi hasil perbandingan, Anda dapat mengadopsi salah satu alternatif berikut untuk memanggil Equals metode atau CompareTo :

  • Math.Round Panggil metode untuk memastikan bahwa kedua nilai memiliki presisi yang sama. Contoh berikut memodifikasi contoh sebelumnya untuk menggunakan pendekatan ini sehingga dua nilai pecahan setara.

    using System;
    
    public class Example2
    {
        public static void Main()
        {
            double value1 = .333333333333333;
            double value2 = 1.0 / 3;
            int precision = 7;
            value1 = Math.Round(value1, precision);
            value2 = 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 v1 = 0.333333333333333
    let v2 = 1. / 3.
    let precision = 7
    let value1 = Math.Round(v1, precision)
    let value2 = Math.Round(v2, precision)
    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 Double = 0.333333333333333
            Dim value2 As Double = 1 / 3
            Dim precision As Integer = 7
            value1 = Math.Round(value1, precision)
            value2 = 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
    

    Masalah presisi masih berlaku untuk pembulatan nilai titik tengah. Untuk informasi lebih lanjut, lihat metode Math.Round(Double, Int32, MidpointRounding).

  • Uji perkiraan kesetaraan daripada kesetaraan. Ini mengharuskan Anda menentukan jumlah absolut di mana kedua nilai dapat berbeda tetapi masih sama, atau Anda menentukan jumlah relatif di mana nilai yang lebih kecil dapat berbeda dari nilai yang lebih besar.

    Peringatan

    Double.Epsilon terkadang digunakan sebagai ukuran absolut jarak antara dua Double nilai saat menguji kesetaraan. Namun, Double.Epsilon mengukur nilai sekecil mungkin yang dapat ditambahkan, atau dikurangi dari, yang Double nilainya nol. Untuk sebagian besar nilai positif dan negatif Double , nilai Double.Epsilon terlalu kecil untuk dideteksi. Oleh karena itu, kecuali untuk nilai yang nol, kami tidak merekomendasikan penggunaannya dalam pengujian untuk kesetaraan.

    Contoh berikut menggunakan pendekatan terakhir untuk menentukan IsApproximatelyEqual metode yang menguji perbedaan relatif antara dua nilai. Ini juga membedakan hasil panggilan ke IsApproximatelyEqual metode dan Equals(Double) metode .

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

Nilai dan pengecualian floating-point

Tidak seperti operasi dengan jenis integral, yang melemparkan pengecualian dalam kasus luapan atau operasi ilegal seperti pembagian dengan nol, operasi dengan nilai floating-point tidak melemparkan pengecualian. Sebaliknya, dalam situasi yang luar biasa, hasil dari operasi floating-point adalah nol, infinitas positif, tak terbatas negatif, atau bukan angka (NaN):

  • Jika hasil operasi floating-point terlalu kecil untuk format tujuan, hasilnya adalah nol. Ini dapat terjadi ketika dua angka yang sangat kecil dikalikan, seperti yang ditunjukkan contoh berikut.

    using System;
    
    public class Example6
    {
        public static void Main()
        {
            Double value1 = 1.1632875981534209e-225;
            Double value2 = 9.1642346778e-175;
            Double result = value1 * value2;
            Console.WriteLine("{0} * {1} = {2}", value1, value2, result);
            Console.WriteLine("{0} = 0: {1}", result, result.Equals(0.0));
        }
    }
    // The example displays the following output:
    //       1.16328759815342E-225 * 9.1642346778E-175 = 0
    //       0 = 0: True
    
    let value1 = 1.1632875981534209e-225
    let value2 = 9.1642346778e-175
    let result = value1 * value2
    printfn $"{value1} * {value2} = {result}"
    printfn $"{result} = 0: {result.Equals 0.0}"
    // The example displays the following output:
    //       1.16328759815342E-225 * 9.1642346778E-175 = 0
    //       0 = 0: True
    
    Module Example7
        Public Sub Main()
            Dim value1 As Double = 1.1632875981534209E-225
            Dim value2 As Double = 9.1642346778E-175
            Dim result As Double = value1 * value2
            Console.WriteLine("{0} * {1} = {2}", value1, value2, result)
            Console.WriteLine("{0} = 0: {1}", result, result.Equals(0.0))
        End Sub
    End Module
    ' The example displays the following output:
    '       1.16328759815342E-225 * 9.1642346778E-175 = 0
    '       0 = 0: True
    
  • Jika besarnya hasil operasi floating-point melebihi rentang format tujuan, hasil operasi adalah PositiveInfinity atau NegativeInfinity, sebagaimana mestinya untuk tanda hasil. Hasil operasi yang meluap Double.MaxValue adalah PositiveInfinity, dan hasil operasi yang meluap Double.MinValue adalah NegativeInfinity, seperti yang ditunjukkan contoh berikut.

    using System;
    
    public class Example7
    {
        public static void Main()
        {
            Double value1 = 4.565e153;
            Double value2 = 6.9375e172;
            Double result = value1 * value2;
            Console.WriteLine("PositiveInfinity: {0}",
                               Double.IsPositiveInfinity(result));
            Console.WriteLine("NegativeInfinity: {0}\n",
                              Double.IsNegativeInfinity(result));
    
            value1 = -value1;
            result = value1 * value2;
            Console.WriteLine("PositiveInfinity: {0}",
                               Double.IsPositiveInfinity(result));
            Console.WriteLine("NegativeInfinity: {0}",
                              Double.IsNegativeInfinity(result));
        }
    }
    
    // The example displays the following output:
    //       PositiveInfinity: True
    //       NegativeInfinity: False
    //
    //       PositiveInfinity: False
    //       NegativeInfinity: True
    
    open System
    
    let value1 = 4.565e153
    let value2 = 6.9375e172
    let result = value1 * value2
    printfn $"PositiveInfinity: {Double.IsPositiveInfinity result}"
    printfn $"NegativeInfinity: {Double.IsNegativeInfinity result}\n"
    
    let value3 = - value1
    let result2 = value2 * value3
    printfn $"PositiveInfinity: {Double.IsPositiveInfinity result2}"
    printfn $"NegativeInfinity: {Double.IsNegativeInfinity result2}"
    
    // The example displays the following output:
    //       PositiveInfinity: True
    //       NegativeInfinity: False
    //
    //       PositiveInfinity: False
    //       NegativeInfinity: True
    
    Module Example8
        Public Sub Main()
            Dim value1 As Double = 4.565E+153
            Dim value2 As Double = 6.9375E+172
            Dim result As Double = value1 * value2
            Console.WriteLine("PositiveInfinity: {0}",
                             Double.IsPositiveInfinity(result))
            Console.WriteLine("NegativeInfinity: {0}",
                            Double.IsNegativeInfinity(result))
            Console.WriteLine()
            value1 = -value1
            result = value1 * value2
            Console.WriteLine("PositiveInfinity: {0}",
                             Double.IsPositiveInfinity(result))
            Console.WriteLine("NegativeInfinity: {0}",
                            Double.IsNegativeInfinity(result))
        End Sub
    End Module
    ' The example displays the following output:
    '       PositiveInfinity: True
    '       NegativeInfinity: False
    '       
    '       PositiveInfinity: False
    '       NegativeInfinity: True
    

    PositiveInfinity juga dihasilkan dari pembagian dengan nol dengan dividen positif, dan NegativeInfinity hasil dari pembagian dengan nol dengan dividen negatif.

  • Jika operasi floating-point tidak valid, hasil operasinya adalah NaN. Misalnya, NaN hasil dari operasi berikut:

    • Pembagian dengan nol dengan dividen nol. Perhatikan bahwa kasus pembagian lainnya dengan nol menghasilkan atau PositiveInfinityNegativeInfinity.

    • Setiap operasi floating-point dengan input yang tidak valid. Misalnya, memanggil Math.Sqrt metode dengan nilai negatif mengembalikan NaN, seperti halnya Math.Acos memanggil metode dengan nilai yang lebih besar dari satu atau kurang dari yang negatif.

    • Setiap operasi dengan argumen yang nilainya adalah Double.NaN.

Konversi jenis

Struktur Double tidak menentukan operator konversi eksplisit atau implisit; sebaliknya, konversi diimplementasikan oleh pengkompilasi.

Konversi nilai jenis numerik primitif ke Double adalah konversi yang melebar dan oleh karena itu tidak memerlukan operator transmisi eksplisit atau panggilan ke metode konversi kecuali kompilator secara eksplisit memerlukannya. Misalnya, pengkompilasi C# memerlukan operator transmisi untuk konversi dari Decimal ke Double, sementara pengkompilasi Visual Basic tidak. Contoh berikut mengonversi nilai minimum atau maksimum jenis numerik primitif lainnya menjadi Double.

using System;

public class Example4
{
    public static void Main()
    {
        dynamic[] values = { Byte.MinValue, Byte.MaxValue, Decimal.MinValue,
                           Decimal.MaxValue, Int16.MinValue, Int16.MaxValue,
                           Int32.MinValue, Int32.MaxValue, Int64.MinValue,
                           Int64.MaxValue, SByte.MinValue, SByte.MaxValue,
                           Single.MinValue, Single.MaxValue, UInt16.MinValue,
                           UInt16.MaxValue, UInt32.MinValue, UInt32.MaxValue,
                           UInt64.MinValue, UInt64.MaxValue };
        double dblValue;
        foreach (var value in values)
        {
            if (value.GetType() == typeof(Decimal))
                dblValue = (Double)value;
            else
                dblValue = value;
            Console.WriteLine("{0} ({1}) --> {2:R} ({3})",
                              value, value.GetType().Name,
                              dblValue, dblValue.GetType().Name);
        }
    }
}
// The example displays the following output:
//    0 (Byte) --> 0 (Double)
//    255 (Byte) --> 255 (Double)
//    -79228162514264337593543950335 (Decimal) --> -7.9228162514264338E+28 (Double)
//    79228162514264337593543950335 (Decimal) --> 7.9228162514264338E+28 (Double)
//    -32768 (Int16) --> -32768 (Double)
//    32767 (Int16) --> 32767 (Double)
//    -2147483648 (Int32) --> -2147483648 (Double)
//    2147483647 (Int32) --> 2147483647 (Double)
//    -9223372036854775808 (Int64) --> -9.2233720368547758E+18 (Double)
//    9223372036854775807 (Int64) --> 9.2233720368547758E+18 (Double)
//    -128 (SByte) --> -128 (Double)
//    127 (SByte) --> 127 (Double)
//    -3.402823E+38 (Single) --> -3.4028234663852886E+38 (Double)
//    3.402823E+38 (Single) --> 3.4028234663852886E+38 (Double)
//    0 (UInt16) --> 0 (Double)
//    65535 (UInt16) --> 65535 (Double)
//    0 (UInt32) --> 0 (Double)
//    4294967295 (UInt32) --> 4294967295 (Double)
//    0 (UInt64) --> 0 (Double)
//    18446744073709551615 (UInt64) --> 1.8446744073709552E+19 (Double)
open System

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

for value in values do
    let dblValue = value :?> double
    printfn $"{value} ({value.GetType().Name}) --> {dblValue:R} ({dblValue.GetType().Name})"
// The example displays the following output:
//    0 (Byte) --> 0 (Double)
//    255 (Byte) --> 255 (Double)
//    -79228162514264337593543950335 (Decimal) --> -7.9228162514264338E+28 (Double)
//    79228162514264337593543950335 (Decimal) --> 7.9228162514264338E+28 (Double)
//    -32768 (Int16) --> -32768 (Double)
//    32767 (Int16) --> 32767 (Double)
//    -2147483648 (Int32) --> -2147483648 (Double)
//    2147483647 (Int32) --> 2147483647 (Double)
//    -9223372036854775808 (Int64) --> -9.2233720368547758E+18 (Double)
//    9223372036854775807 (Int64) --> 9.2233720368547758E+18 (Double)
//    -128 (SByte) --> -128 (Double)
//    127 (SByte) --> 127 (Double)
//    -3.402823E+38 (Single) --> -3.4028234663852886E+38 (Double)
//    3.402823E+38 (Single) --> 3.4028234663852886E+38 (Double)
//    0 (UInt16) --> 0 (Double)
//    65535 (UInt16) --> 65535 (Double)
//    0 (UInt32) --> 0 (Double)
//    4294967295 (UInt32) --> 4294967295 (Double)
//    0 (UInt64) --> 0 (Double)
//    18446744073709551615 (UInt64) --> 1.8446744073709552E+19 (Double)
Module Example5
    Public Sub Main()
        Dim values() As Object = {Byte.MinValue, Byte.MaxValue, Decimal.MinValue,
                                 Decimal.MaxValue, Int16.MinValue, Int16.MaxValue,
                                 Int32.MinValue, Int32.MaxValue, Int64.MinValue,
                                 Int64.MaxValue, SByte.MinValue, SByte.MaxValue,
                                 Single.MinValue, Single.MaxValue, UInt16.MinValue,
                                 UInt16.MaxValue, UInt32.MinValue, UInt32.MaxValue,
                                 UInt64.MinValue, UInt64.MaxValue}
        Dim dblValue As Double
        For Each value In values
            dblValue = value
            Console.WriteLine("{0} ({1}) --> {2:R} ({3})",
                           value, value.GetType().Name,
                           dblValue, dblValue.GetType().Name)
        Next
    End Sub
End Module
' The example displays the following output:
'    0 (Byte) --> 0 (Double)
'    255 (Byte) --> 255 (Double)
'    -79228162514264337593543950335 (Decimal) --> -7.9228162514264338E+28 (Double)
'    79228162514264337593543950335 (Decimal) --> 7.9228162514264338E+28 (Double)
'    -32768 (Int16) --> -32768 (Double)
'    32767 (Int16) --> 32767 (Double)
'    -2147483648 (Int32) --> -2147483648 (Double)
'    2147483647 (Int32) --> 2147483647 (Double)
'    -9223372036854775808 (Int64) --> -9.2233720368547758E+18 (Double)
'    9223372036854775807 (Int64) --> 9.2233720368547758E+18 (Double)
'    -128 (SByte) --> -128 (Double)
'    127 (SByte) --> 127 (Double)
'    -3.402823E+38 (Single) --> -3.4028234663852886E+38 (Double)
'    3.402823E+38 (Single) --> 3.4028234663852886E+38 (Double)
'    0 (UInt16) --> 0 (Double)
'    65535 (UInt16) --> 65535 (Double)
'    0 (UInt32) --> 0 (Double)
'    4294967295 (UInt32) --> 4294967295 (Double)
'    0 (UInt64) --> 0 (Double)
'    18446744073709551615 (UInt64) --> 1.8446744073709552E+19 (Double)

Selain itu, Single nilai Single.NaN, , Single.PositiveInfinitydan Single.NegativeInfinity konversi ke Double.NaN, Double.PositiveInfinity, dan Double.NegativeInfinity, masing-masing.

Perhatikan bahwa konversi nilai beberapa jenis numerik ke Double nilai dapat melibatkan hilangnya presisi. Seperti yang diilustrasikan contoh, hilangnya presisi dimungkinkan saat mengonversi Decimal, Int64, dan UInt64 nilai menjadi Double nilai.

Konversi Double nilai ke nilai dari jenis data numerik primitif lainnya adalah konversi yang menyempit dan memerlukan operator transmisi (dalam C#), metode konversi (di Visual Basic), atau panggilan ke Convert metode. Nilai yang berada di luar rentang jenis data target, yang ditentukan oleh jenis MinValue target dan MaxValue properti, berulah seperti yang ditunjukkan dalam tabel berikut.

Jenis target Hasil
Jenis integral apa pun Pengecualian OverflowException jika konversi terjadi dalam konteks yang dicentang.

Jika konversi terjadi dalam konteks yang tidak dicentang (default dalam C#), operasi konversi berhasil tetapi nilai meluap.
Decimal Pengecualian OverflowException .
Single Single.NegativeInfinity untuk nilai negatif.

Single.PositiveInfinity untuk nilai positif.

Selain itu, Double.NaN, , Double.PositiveInfinitydan Double.NegativeInfinity melemparkan OverflowException untuk konversi ke bilangan bulat dalam konteks yang dicentang, tetapi nilai-nilai ini meluap saat dikonversi menjadi bilangan bulat dalam konteks yang tidak dicentang. Untuk konversi ke Decimal, mereka selalu melempar .OverflowException Untuk konversi ke Single, mereka masing-masing mengonversi ke Single.NaN, Single.PositiveInfinity, dan Single.NegativeInfinity, .

Hilangnya presisi dapat mengakibatkan konversi Double nilai ke jenis numerik lain. Dalam kasus konversi ke salah satu jenis integral, seperti yang ditunjukkan output dari contoh, komponen pecahan hilang ketika Double nilai dibulatkan (seperti dalam Visual Basic) atau dipotong (seperti dalam C#). Untuk konversi ke Decimal nilai dan Single , Double nilai mungkin tidak memiliki representasi yang tepat dalam jenis data target.

Contoh berikut mengonversi sejumlah Double nilai menjadi beberapa jenis numerik lainnya. Konversi terjadi dalam konteks yang diperiksa di Visual Basic (default), di C# (karena kata kunci yang diperiksa ), dan di F# (karena modul Diperiksa ). Output dari contoh menunjukkan hasil untuk konversi dalam konteks yang tidak dicentang. Anda dapat melakukan konversi dalam konteks yang tidak dicentang di Visual Basic dengan mengkompilasi dengan /removeintchecks+ sakelar kompilator, di C# dengan mengomentari checked pernyataan, dan di F# dengan mengomentari open Checked pernyataan.

using System;

public class Example5
{
    public static void Main()
    {
        Double[] values = { Double.MinValue, -67890.1234, -12345.6789,
                          12345.6789, 67890.1234, Double.MaxValue,
                          Double.NaN, Double.PositiveInfinity,
                          Double.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);
                }
                try
                {
                    Single sValue = (float)value;
                    Console.WriteLine("{0} ({1}) --> {2} ({3})",
                                      value, value.GetType().Name,
                                      sValue, sValue.GetType().Name);
                }
                catch (OverflowException)
                {
                    Console.WriteLine("Unable to convert {0} to Single.", value);
                }
                Console.WriteLine();
            }
        }
    }
}
// The example displays the following output for conversions performed
// in a checked context:
//       Unable to convert -1.79769313486232E+308 to Int64.
//       Unable to convert -1.79769313486232E+308 to UInt64.
//       Unable to convert -1.79769313486232E+308 to Decimal.
//       -1.79769313486232E+308 (Double) --> -Infinity (Single)
//
//       -67890.1234 (Double) --> -67890 (0xFFFFFFFFFFFEF6CE) (Int64)
//       Unable to convert -67890.1234 to UInt64.
//       -67890.1234 (Double) --> -67890.1234 (Decimal)
//       -67890.1234 (Double) --> -67890.13 (Single)
//
//       -12345.6789 (Double) --> -12345 (0xFFFFFFFFFFFFCFC7) (Int64)
//       Unable to convert -12345.6789 to UInt64.
//       -12345.6789 (Double) --> -12345.6789 (Decimal)
//       -12345.6789 (Double) --> -12345.68 (Single)
//
//       12345.6789 (Double) --> 12345 (0x0000000000003039) (Int64)
//       12345.6789 (Double) --> 12345 (0x0000000000003039) (UInt64)
//       12345.6789 (Double) --> 12345.6789 (Decimal)
//       12345.6789 (Double) --> 12345.68 (Single)
//
//       67890.1234 (Double) --> 67890 (0x0000000000010932) (Int64)
//       67890.1234 (Double) --> 67890 (0x0000000000010932) (UInt64)
//       67890.1234 (Double) --> 67890.1234 (Decimal)
//       67890.1234 (Double) --> 67890.13 (Single)
//
//       Unable to convert 1.79769313486232E+308 to Int64.
//       Unable to convert 1.79769313486232E+308 to UInt64.
//       Unable to convert 1.79769313486232E+308 to Decimal.
//       1.79769313486232E+308 (Double) --> Infinity (Single)
//
//       Unable to convert NaN to Int64.
//       Unable to convert NaN to UInt64.
//       Unable to convert NaN to Decimal.
//       NaN (Double) --> NaN (Single)
//
//       Unable to convert Infinity to Int64.
//       Unable to convert Infinity to UInt64.
//       Unable to convert Infinity to Decimal.
//       Infinity (Double) --> Infinity (Single)
//
//       Unable to convert -Infinity to Int64.
//       Unable to convert -Infinity to UInt64.
//       Unable to convert -Infinity to Decimal.
//       -Infinity (Double) --> -Infinity (Single)
// The example displays the following output for conversions performed
// in an unchecked context:
//       -1.79769313486232E+308 (Double) --> -9223372036854775808 (0x8000000000000000) (Int64)
//       -1.79769313486232E+308 (Double) --> 9223372036854775808 (0x8000000000000000) (UInt64)
//       Unable to convert -1.79769313486232E+308 to Decimal.
//       -1.79769313486232E+308 (Double) --> -Infinity (Single)
//
//       -67890.1234 (Double) --> -67890 (0xFFFFFFFFFFFEF6CE) (Int64)
//       -67890.1234 (Double) --> 18446744073709483726 (0xFFFFFFFFFFFEF6CE) (UInt64)
//       -67890.1234 (Double) --> -67890.1234 (Decimal)
//       -67890.1234 (Double) --> -67890.13 (Single)
//
//       -12345.6789 (Double) --> -12345 (0xFFFFFFFFFFFFCFC7) (Int64)
//       -12345.6789 (Double) --> 18446744073709539271 (0xFFFFFFFFFFFFCFC7) (UInt64)
//       -12345.6789 (Double) --> -12345.6789 (Decimal)
//       -12345.6789 (Double) --> -12345.68 (Single)
//
//       12345.6789 (Double) --> 12345 (0x0000000000003039) (Int64)
//       12345.6789 (Double) --> 12345 (0x0000000000003039) (UInt64)
//       12345.6789 (Double) --> 12345.6789 (Decimal)
//       12345.6789 (Double) --> 12345.68 (Single)
//
//       67890.1234 (Double) --> 67890 (0x0000000000010932) (Int64)
//       67890.1234 (Double) --> 67890 (0x0000000000010932) (UInt64)
//       67890.1234 (Double) --> 67890.1234 (Decimal)
//       67890.1234 (Double) --> 67890.13 (Single)
//
//       1.79769313486232E+308 (Double) --> -9223372036854775808 (0x8000000000000000) (Int64)
//       1.79769313486232E+308 (Double) --> 0 (0x0000000000000000) (UInt64)
//       Unable to convert 1.79769313486232E+308 to Decimal.
//       1.79769313486232E+308 (Double) --> Infinity (Single)
//
//       NaN (Double) --> -9223372036854775808 (0x8000000000000000) (Int64)
//       NaN (Double) --> 0 (0x0000000000000000) (UInt64)
//       Unable to convert NaN to Decimal.
//       NaN (Double) --> NaN (Single)
//
//       Infinity (Double) --> -9223372036854775808 (0x8000000000000000) (Int64)
//       Infinity (Double) --> 0 (0x0000000000000000) (UInt64)
//       Unable to convert Infinity to Decimal.
//       Infinity (Double) --> Infinity (Single)
//
//       -Infinity (Double) --> -9223372036854775808 (0x8000000000000000) (Int64)
//       -Infinity (Double) --> 9223372036854775808 (0x8000000000000000) (UInt64)
//       Unable to convert -Infinity to Decimal.
//       -Infinity (Double) --> -Infinity (Single)
open System
open Checked

let values = 
    [| Double.MinValue; -67890.1234; -12345.6789
       12345.6789; 67890.1234; Double.MaxValue
       Double.NaN; Double.PositiveInfinity;
       Double.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."
    try
        let sValue = float32 value
        printfn $"{value} ({value.GetType().Name}) --> {sValue} ({sValue.GetType().Name})"
    with :? OverflowException ->
        printfn $"Unable to convert {value} to Single."
    printfn ""
// The example displays the following output for conversions performed
// in a checked context:
//       Unable to convert -1.79769313486232E+308 to Int64.
//       Unable to convert -1.79769313486232E+308 to UInt64.
//       Unable to convert -1.79769313486232E+308 to Decimal.
//       -1.79769313486232E+308 (Double) --> -Infinity (Single)
//
//       -67890.1234 (Double) --> -67890 (0xFFFFFFFFFFFEF6CE) (Int64)
//       Unable to convert -67890.1234 to UInt64.
//       -67890.1234 (Double) --> -67890.1234 (Decimal)
//       -67890.1234 (Double) --> -67890.13 (Single)
//
//       -12345.6789 (Double) --> -12345 (0xFFFFFFFFFFFFCFC7) (Int64)
//       Unable to convert -12345.6789 to UInt64.
//       -12345.6789 (Double) --> -12345.6789 (Decimal)
//       -12345.6789 (Double) --> -12345.68 (Single)
//
//       12345.6789 (Double) --> 12345 (0x0000000000003039) (Int64)
//       12345.6789 (Double) --> 12345 (0x0000000000003039) (UInt64)
//       12345.6789 (Double) --> 12345.6789 (Decimal)
//       12345.6789 (Double) --> 12345.68 (Single)
//
//       67890.1234 (Double) --> 67890 (0x0000000000010932) (Int64)
//       67890.1234 (Double) --> 67890 (0x0000000000010932) (UInt64)
//       67890.1234 (Double) --> 67890.1234 (Decimal)
//       67890.1234 (Double) --> 67890.13 (Single)
//
//       Unable to convert 1.79769313486232E+308 to Int64.
//       Unable to convert 1.79769313486232E+308 to UInt64.
//       Unable to convert 1.79769313486232E+308 to Decimal.
//       1.79769313486232E+308 (Double) --> Infinity (Single)
//
//       Unable to convert NaN to Int64.
//       Unable to convert NaN to UInt64.
//       Unable to convert NaN to Decimal.
//       NaN (Double) --> NaN (Single)
//
//       Unable to convert Infinity to Int64.
//       Unable to convert Infinity to UInt64.
//       Unable to convert Infinity to Decimal.
//       Infinity (Double) --> Infinity (Single)
//
//       Unable to convert -Infinity to Int64.
//       Unable to convert -Infinity to UInt64.
//       Unable to convert -Infinity to Decimal.
//       -Infinity (Double) --> -Infinity (Single)
// The example displays the following output for conversions performed
// in an unchecked context:
//       -1.79769313486232E+308 (Double) --> -9223372036854775808 (0x8000000000000000) (Int64)
//       -1.79769313486232E+308 (Double) --> 9223372036854775808 (0x8000000000000000) (UInt64)
//       Unable to convert -1.79769313486232E+308 to Decimal.
//       -1.79769313486232E+308 (Double) --> -Infinity (Single)
//
//       -67890.1234 (Double) --> -67890 (0xFFFFFFFFFFFEF6CE) (Int64)
//       -67890.1234 (Double) --> 18446744073709483726 (0xFFFFFFFFFFFEF6CE) (UInt64)
//       -67890.1234 (Double) --> -67890.1234 (Decimal)
//       -67890.1234 (Double) --> -67890.13 (Single)
//
//       -12345.6789 (Double) --> -12345 (0xFFFFFFFFFFFFCFC7) (Int64)
//       -12345.6789 (Double) --> 18446744073709539271 (0xFFFFFFFFFFFFCFC7) (UInt64)
//       -12345.6789 (Double) --> -12345.6789 (Decimal)
//       -12345.6789 (Double) --> -12345.68 (Single)
//
//       12345.6789 (Double) --> 12345 (0x0000000000003039) (Int64)
//       12345.6789 (Double) --> 12345 (0x0000000000003039) (UInt64)
//       12345.6789 (Double) --> 12345.6789 (Decimal)
//       12345.6789 (Double) --> 12345.68 (Single)
//
//       67890.1234 (Double) --> 67890 (0x0000000000010932) (Int64)
//       67890.1234 (Double) --> 67890 (0x0000000000010932) (UInt64)
//       67890.1234 (Double) --> 67890.1234 (Decimal)
//       67890.1234 (Double) --> 67890.13 (Single)
//
//       1.79769313486232E+308 (Double) --> -9223372036854775808 (0x8000000000000000) (Int64)
//       1.79769313486232E+308 (Double) --> 0 (0x0000000000000000) (UInt64)
//       Unable to convert 1.79769313486232E+308 to Decimal.
//       1.79769313486232E+308 (Double) --> Infinity (Single)
//
//       NaN (Double) --> -9223372036854775808 (0x8000000000000000) (Int64)
//       NaN (Double) --> 0 (0x0000000000000000) (UInt64)
//       Unable to convert NaN to Decimal.
//       NaN (Double) --> NaN (Single)
//
//       Infinity (Double) --> -9223372036854775808 (0x8000000000000000) (Int64)
//       Infinity (Double) --> 0 (0x0000000000000000) (UInt64)
//       Unable to convert Infinity to Decimal.
//       Infinity (Double) --> Infinity (Single)
//
//       -Infinity (Double) --> -9223372036854775808 (0x8000000000000000) (Int64)
//       -Infinity (Double) --> 9223372036854775808 (0x8000000000000000) (UInt64)
//       Unable to convert -Infinity to Decimal.
//       -Infinity (Double) --> -Infinity (Single)
Module Example6
    Public Sub Main()
        Dim values() As Double = {Double.MinValue, -67890.1234, -12345.6789,
                                 12345.6789, 67890.1234, Double.MaxValue,
                                 Double.NaN, Double.PositiveInfinity,
                                 Double.NegativeInfinity}
        For Each value In values
            Try
                Dim lValue As Int64 = 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
            Try
                Dim sValue As Single = CSng(value)
                Console.WriteLine("{0} ({1}) --> {2} ({3})",
                               value, value.GetType().Name,
                               sValue, sValue.GetType().Name)
            Catch e As OverflowException
                Console.WriteLine("Unable to convert {0} to Single.", value)
            End Try
            Console.WriteLine()
        Next
    End Sub
End Module
' The example displays the following output for conversions performed
' in a checked context:
'       Unable to convert -1.79769313486232E+308 to Int64.
'       Unable to convert -1.79769313486232E+308 to UInt64.
'       Unable to convert -1.79769313486232E+308 to Decimal.
'       -1.79769313486232E+308 (Double) --> -Infinity (Single)
'
'       -67890.1234 (Double) --> -67890 (0xFFFFFFFFFFFEF6CE) (Int64)
'       Unable to convert -67890.1234 to UInt64.
'       -67890.1234 (Double) --> -67890.1234 (Decimal)
'       -67890.1234 (Double) --> -67890.13 (Single)
'
'       -12345.6789 (Double) --> -12346 (0xFFFFFFFFFFFFCFC6) (Int64)
'       Unable to convert -12345.6789 to UInt64.
'       -12345.6789 (Double) --> -12345.6789 (Decimal)
'       -12345.6789 (Double) --> -12345.68 (Single)
'
'       12345.6789 (Double) --> 12346 (0x000000000000303A) (Int64)
'       12345.6789 (Double) --> 12346 (0x000000000000303A) (UInt64)
'       12345.6789 (Double) --> 12345.6789 (Decimal)
'       12345.6789 (Double) --> 12345.68 (Single)
'
'       67890.1234 (Double) --> 67890 (0x0000000000010932) (Int64)
'       67890.1234 (Double) --> 67890 (0x0000000000010932) (UInt64)
'       67890.1234 (Double) --> 67890.1234 (Decimal)
'       67890.1234 (Double) --> 67890.13 (Single)
'
'       Unable to convert 1.79769313486232E+308 to Int64.
'       Unable to convert 1.79769313486232E+308 to UInt64.
'       Unable to convert 1.79769313486232E+308 to Decimal.
'       1.79769313486232E+308 (Double) --> Infinity (Single)
'
'       Unable to convert NaN to Int64.
'       Unable to convert NaN to UInt64.
'       Unable to convert NaN to Decimal.
'       NaN (Double) --> NaN (Single)
'
'       Unable to convert Infinity to Int64.
'       Unable to convert Infinity to UInt64.
'       Unable to convert Infinity to Decimal.
'       Infinity (Double) --> Infinity (Single)
'
'       Unable to convert -Infinity to Int64.
'       Unable to convert -Infinity to UInt64.
'       Unable to convert -Infinity to Decimal.
'       -Infinity (Double) --> -Infinity (Single)
' The example displays the following output for conversions performed
' in an unchecked context:
'       -1.79769313486232E+308 (Double) --> -9223372036854775808 (0x8000000000000000) (Int64)
'       -1.79769313486232E+308 (Double) --> 9223372036854775808 (0x8000000000000000) (UInt64)
'       Unable to convert -1.79769313486232E+308 to Decimal.
'       -1.79769313486232E+308 (Double) --> -Infinity (Single)
'
'       -67890.1234 (Double) --> -67890 (0xFFFFFFFFFFFEF6CE) (Int64)
'       -67890.1234 (Double) --> 18446744073709483726 (0xFFFFFFFFFFFEF6CE) (UInt64)
'       -67890.1234 (Double) --> -67890.1234 (Decimal)
'       -67890.1234 (Double) --> -67890.13 (Single)
'
'       -12345.6789 (Double) --> -12346 (0xFFFFFFFFFFFFCFC6) (Int64)
'       -12345.6789 (Double) --> 18446744073709539270 (0xFFFFFFFFFFFFCFC6) (UInt64)
'       -12345.6789 (Double) --> -12345.6789 (Decimal)
'       -12345.6789 (Double) --> -12345.68 (Single)
'
'       12345.6789 (Double) --> 12346 (0x000000000000303A) (Int64)
'       12345.6789 (Double) --> 12346 (0x000000000000303A) (UInt64)
'       12345.6789 (Double) --> 12345.6789 (Decimal)
'       12345.6789 (Double) --> 12345.68 (Single)
'
'       67890.1234 (Double) --> 67890 (0x0000000000010932) (Int64)
'       67890.1234 (Double) --> 67890 (0x0000000000010932) (UInt64)
'       67890.1234 (Double) --> 67890.1234 (Decimal)
'       67890.1234 (Double) --> 67890.13 (Single)
'
'       1.79769313486232E+308 (Double) --> -9223372036854775808 (0x8000000000000000) (Int64)
'       1.79769313486232E+308 (Double) --> 0 (0x0000000000000000) (UInt64)
'       Unable to convert 1.79769313486232E+308 to Decimal.
'       1.79769313486232E+308 (Double) --> Infinity (Single)
'
'       NaN (Double) --> -9223372036854775808 (0x8000000000000000) (Int64)
'       NaN (Double) --> 0 (0x0000000000000000) (UInt64)
'       Unable to convert NaN to Decimal.
'       NaN (Double) --> NaN (Single)
'
'       Infinity (Double) --> -9223372036854775808 (0x8000000000000000) (Int64)
'       Infinity (Double) --> 0 (0x0000000000000000) (UInt64)
'       Unable to convert Infinity to Decimal.
'       Infinity (Double) --> Infinity (Single)
'
'       -Infinity (Double) --> -9223372036854775808 (0x8000000000000000) (Int64)
'       -Infinity (Double) --> 9223372036854775808 (0x8000000000000000) (UInt64)
'       Unable to convert -Infinity to Decimal.
'       -Infinity (Double) --> -Infinity (Single)

Untuk informasi selengkapnya tentang konversi jenis numerik, lihat Konversi Tipe di .NET dan Jenis Tabel Konversi.

Fungsionalitas floating-point

Struktur Double dan jenis terkait menyediakan metode untuk melakukan operasi di area berikut:

  • Perbandingan nilai. Anda dapat memanggil Equals metode untuk menentukan apakah dua Double nilai sama, atau CompareTo metode untuk menentukan hubungan antara dua nilai.

    Struktur ini Double juga mendukung serangkaian operator perbandingan lengkap. Misalnya, Anda dapat menguji kesetaraan atau ketidaksetaraan, atau menentukan apakah satu nilai lebih besar dari atau sama dengan nilai lainnya. Jika salah satu operand adalah jenis numerik selain Double, itu dikonversi ke Double sebelum melakukan perbandingan.

    Peringatan

    Karena perbedaan presisi, dua Double nilai yang Anda harapkan sama mungkin berubah menjadi tidak sama, yang memengaruhi hasil perbandingan. Lihat bagian Uji untuk kesetaraan untuk informasi selengkapnya tentang membandingkan dua Double nilai.

    Anda juga dapat memanggil IsNaNmetode , IsInfinity, IsPositiveInfinity, dan IsNegativeInfinity untuk menguji nilai khusus ini.

  • Operasi matematika. Operasi aritmatika umum, seperti penambahan, pengurangan, perkalian, dan pembagian, diimplementasikan oleh pengkompilasi bahasa dan instruksi Common Intermediate Language (CIL), bukan dengan Double metode. Jika salah satu operand dalam operasi matematika adalah jenis numerik selain Double, itu dikonversi ke Double sebelum melakukan operasi. Hasil operasi juga merupakan Double nilai.

    Operasi matematika lainnya dapat dilakukan dengan memanggil static metode (Shared dalam Visual Basic) di System.Math kelas . Ini termasuk metode tambahan yang umum digunakan untuk aritmetika (seperti Math.Abs, , Math.Signdan Math.Sqrt), geometri (seperti Math.Cos dan Math.Sin), dan kalkulus (seperti Math.Log).

    Anda juga dapat memanipulasi bit individual dalam nilai Double . Metode ini BitConverter.DoubleToInt64Bits mempertahankan Double pola bit nilai dalam bilangan bulat 64-bit. Metode mengembalikan BitConverter.GetBytes(Double) pola bitnya dalam array byte.

  • Pembulatan. Pembulatan sering digunakan sebagai teknik untuk mengurangi dampak perbedaan antara nilai yang disebabkan oleh masalah representasi dan presisi floating-point. Anda dapat membulatkan Double nilai dengan memanggil Math.Round metode .

  • Pemformatan. Anda dapat mengonversi Double nilai ke representasi stringnya dengan memanggil ToString metode atau dengan menggunakan fitur pemformatan komposit. Untuk informasi tentang bagaimana string format mengontrol representasi string dari nilai floating-point, lihat topik String Format Numerik Standar dan String Format Numerik Kustom.

  • Mengurai string. Anda dapat mengonversi representasi string dari nilai floating-point menjadi Double nilai dengan memanggil Parse metode atau TryParse . Jika operasi penguraian gagal, Parse metode melempar pengecualian, sedangkan TryParse metode mengembalikan false.

  • Konversi jenis. Struktur ini Double menyediakan implementasi antarmuka eksplisit untuk IConvertible antarmuka, yang mendukung konversi antara dua jenis data .NET standar. Pengkompilasi bahasa juga mendukung konversi implisit nilai dari semua jenis numerik standar lainnya ke Double nilai. Konversi nilai dari jenis numerik standar apa pun ke adalah Double konversi yang melebar dan tidak memerlukan pengguna operator transmisi atau metode konversi,

    Namun, konversi nilai Int64 dan Single dapat melibatkan hilangnya presisi. Tabel berikut ini mencantumkan perbedaan presisi untuk masing-masing jenis ini:

    Jenis Presisi maksimum Presisi internal
    Double 15 17
    Int64 19 digit desimal 19 digit desimal
    Single 7 digit desimal 9 digit desimal

    Masalah presisi paling sering memengaruhi Single nilai yang dikonversi ke Double nilai. Dalam contoh berikut, dua nilai yang dihasilkan oleh operasi pembagian yang identik tidak sama karena salah satu nilainya adalah nilai floating point presisi tunggal yang dikonversi ke Double.

    using System;
    
    public class Example13
    {
        public static void Main()
        {
            Double value = .1;
            Double result1 = value * 10;
            Double result2 = 0;
            for (int ctr = 1; ctr <= 10; ctr++)
                result2 += value;
    
            Console.WriteLine(".1 * 10:           {0:R}", result1);
            Console.WriteLine(".1 Added 10 times: {0:R}", result2);
        }
    }
    // The example displays the following output:
    //       .1 * 10:           1
    //       .1 Added 10 times: 0.99999999999999989
    
    let value = 0.1
    let result1 = value * 10.
    let mutable result2 = 0.
    for i = 1 to 10 do
        result2 <- result2 + value
    
    printfn $".1 * 10:           {result1:R}"
    printfn $".1 Added 10 times: {result2:R}"
    // The example displays the following output:
    //       .1 * 10:           1
    //       .1 Added 10 times: 0.99999999999999989
    
    Module Example14
        Public Sub Main()
            Dim value As Double = 0.1
            Dim result1 As Double = value * 10
            Dim result2 As Double
            For ctr As Integer = 1 To 10
                result2 += value
            Next
            Console.WriteLine(".1 * 10:           {0:R}", result1)
            Console.WriteLine(".1 Added 10 times: {0:R}", result2)
        End Sub
    End Module
    ' The example displays the following output:
    '       .1 * 10:           1
    '       .1 Added 10 times: 0.99999999999999989
    

Contoh

Contoh kode berikut mengilustrasikan penggunaan Double:

// The Temperature class stores the temperature as a Double
// and delegates most of the functionality to the Double
// implementation.
public class Temperature : IComparable, IFormattable
{
    // IComparable.CompareTo implementation.
    public int CompareTo(object obj) {
        if (obj == null) return 1;

        Temperature temp = obj as Temperature;
        if (obj != null)
            return m_value.CompareTo(temp.m_value);
        else
            throw new ArgumentException("object is not a Temperature");	
    }

    // IFormattable.ToString implementation.
    public string ToString(string format, IFormatProvider provider) {
        if( format != null ) {
            if( format.Equals("F") ) {
                return String.Format("{0}'F", this.Value.ToString());
            }
            if( format.Equals("C") ) {
                return String.Format("{0}'C", this.Celsius.ToString());
            }
        }

        return m_value.ToString(format, provider);
    }

    // Parses the temperature from a string in the form
    // [ws][sign]digits['F|'C][ws]
    public static Temperature Parse(string s, NumberStyles styles, IFormatProvider provider) {
        Temperature temp = new Temperature();

        if( s.TrimEnd(null).EndsWith("'F") ) {
            temp.Value = Double.Parse( s.Remove(s.LastIndexOf('\''), 2), styles, provider);
        }
        else if( s.TrimEnd(null).EndsWith("'C") ) {
            temp.Celsius = Double.Parse( s.Remove(s.LastIndexOf('\''), 2), styles, provider);
        }
        else {
            temp.Value = Double.Parse(s, styles, provider);
        }

        return temp;
    }

    // The value holder
    protected double m_value;

    public double Value {
        get {
            return m_value;
        }
        set {
            m_value = value;
        }
    }

    public double Celsius {
        get {
            return (m_value-32.0)/1.8;
        }
        set {
            m_value = 1.8*value+32.0;
        }
    }
}
// The Temperature class stores the temperature as a Double
// and delegates most of the functionality to the Double
// implementation.
type Temperature() =
    member val Value = 0. with get, set

    member this.Celsius
        with get () = (this.Value - 32.) / 1.8
        and set (value) =
            this.Value <- 1.8 * value + 32.

    // Parses the temperature from a string in the form
    // [ws][sign]digits['F|'C][ws]
    static member Parse(s: string, styles: NumberStyles, provider: IFormatProvider) =
        let temp = Temperature()

        if s.TrimEnd(null).EndsWith "'F" then
            temp.Value <- Double.Parse(s.Remove(s.LastIndexOf '\'', 2), styles, provider)
        elif s.TrimEnd(null).EndsWith "'C" then
            temp.Celsius <- Double.Parse(s.Remove(s.LastIndexOf '\'', 2), styles, provider)
        else
            temp.Value <- Double.Parse(s, styles, provider)
        temp

    interface IComparable with
        // IComparable.CompareTo implementation.
        member this.CompareTo(obj: obj) =
            match obj with 
            | null -> 1
            | :? Temperature as temp ->
                this.Value.CompareTo temp.Value
            | _ ->
                invalidArg "obj" "object is not a Temperature"

    interface IFormattable with
        // IFormattable.ToString implementation.
        member this.ToString(format: string, provider: IFormatProvider) =
            match format with
            | "F" ->
                $"{this.Value}'F"
            | "C" ->
                $"{this.Celsius}'C"
            | _ ->
                this.Value.ToString(format, provider)
' Temperature class stores the value as Double
' and delegates most of the functionality 
' to the Double implementation.
Public Class Temperature
    Implements IComparable, IFormattable

    Public Overloads Function CompareTo(ByVal obj As Object) As Integer _
        Implements IComparable.CompareTo

        If TypeOf obj Is Temperature Then
            Dim temp As Temperature = CType(obj, Temperature)

            Return m_value.CompareTo(temp.m_value)
        End If

        Throw New ArgumentException("object is not a Temperature")
    End Function

    Public Overloads Function ToString(ByVal format As String, ByVal provider As IFormatProvider) As String _
        Implements IFormattable.ToString

        If Not (format Is Nothing) Then
            If format.Equals("F") Then
                Return [String].Format("{0}'F", Me.Value.ToString())
            End If
            If format.Equals("C") Then
                Return [String].Format("{0}'C", Me.Celsius.ToString())
            End If
        End If

        Return m_value.ToString(format, provider)
    End Function

    ' Parses the temperature from a string in form
    ' [ws][sign]digits['F|'C][ws]
    Public Shared Function Parse(ByVal s As String, ByVal styles As NumberStyles, ByVal provider As IFormatProvider) As Temperature
        Dim temp As New Temperature()

        If s.TrimEnd().EndsWith("'F") Then
            temp.Value = Double.Parse(s.Remove(s.LastIndexOf("'"c), 2), styles, provider)
        Else
            If s.TrimEnd().EndsWith("'C") Then
                temp.Celsius = Double.Parse(s.Remove(s.LastIndexOf("'"c), 2), styles, provider)
            Else
                temp.Value = Double.Parse(s, styles, provider)
            End If
        End If
        Return temp
    End Function

    ' The value holder
    Protected m_value As Double

    Public Property Value() As Double
        Get
            Return m_value
        End Get
        Set(ByVal Value As Double)
            m_value = Value
        End Set
    End Property

    Public Property Celsius() As Double
        Get
            Return (m_value - 32) / 1.8
        End Get
        Set(ByVal Value As Double)
            m_value = Value * 1.8 + 32
        End Set
    End Property
End Class