Metode System.Double.Equals
Metode Th Double.Equals(Double) mengimplementasikan System.IEquatable<T> antarmuka, dan berkinerja sedikit lebih baik daripada Double.Equals(Object) karena tidak harus mengonversi obj
parameter menjadi objek.
Melebarkan konversi
Tergantung pada bahasa pemrograman Anda, mungkin untuk membuat Equals kode metode di mana jenis parameter memiliki bit yang lebih sedikit (lebih sempit) daripada jenis instans. Hal ini dimungkinkan karena beberapa bahasa pemrograman melakukan konversi pellebaran implisit yang mewakili parameter sebagai jenis dengan bit sebanyak instans.
Misalnya, misalkan jenis instans adalah Double dan jenis parameternya adalah Int32. Pengkompilasi Microsoft C# menghasilkan instruksi untuk mewakili nilai parameter sebagai Double objek, lalu menghasilkan Double.Equals(Double) metode yang membandingkan nilai instans dan representasi parameter yang diperlebar.
Lihat dokumentasi bahasa pemrograman Anda untuk menentukan apakah pengkompilasinya melakukan konversi tipe numerik yang melebar implisit. Untuk informasi selengkapnya, lihat topik Ketik Tabel Konversi.
Presisi dalam perbandingan
Metode Equals ini harus digunakan dengan hati-hati, karena dua nilai yang tampaknya setara dapat tidak sama karena presisi yang berbeda dari dua nilai. Contoh berikut melaporkan bahwa Double nilai .333333 dan Double nilai yang dikembalikan dengan membalai 1 dengan 3 tidak sama.
// Initialize two doubles with apparently identical values
double double1 = .33333;
double double2 = (double) 1/3;
// Compare them for equality
Console.WriteLine(double1.Equals(double2)); // displays false
// Initialize two doubles with apparently identical values
let double1 = 0.33333
let double2 = double (1 / 3)
// Compare them for equality
printfn $"{double1.Equals double2}" // displays false
' Initialize two doubles with apparently identical values
Dim double1 As Double = .33333
Dim double2 As Double = 1/3
' Compare them for equality
Console.WriteLine(double1.Equals(double2)) ' displays False
Daripada membandingkan kesetaraan, satu teknik melibatkan penentuan margin relatif selisih yang dapat diterima antara dua nilai (seperti .001% dari salah satu nilai). Jika nilai absolut perbedaan antara kedua nilai kurang dari atau sama dengan margin tersebut, perbedaannya kemungkinan disebabkan oleh perbedaan presisi dan, oleh karena itu, nilainya kemungkinan sama. Contoh berikut menggunakan teknik ini untuk membandingkan .33333 dan 1/3, dua Double nilai yang ditemukan contoh kode sebelumnya tidak sama. Dalam hal ini, nilainya sama.
// Initialize two doubles with apparently identical values
double double1 = .333333;
double double2 = (double) 1/3;
// Define the tolerance for variation in their values
double difference = Math.Abs(double1 * .00001);
// Compare the values
// The output to the console indicates that the two values are equal
if (Math.Abs(double1 - double2) <= difference)
Console.WriteLine("double1 and double2 are equal.");
else
Console.WriteLine("double1 and double2 are unequal.");
// Initialize two doubles with apparently identical values
let double1 = 0.333333
let double2 = double (1 / 3)
// Define the tolerance for variation in their values
let difference = abs (double1 * 0.00001)
// Compare the values
// The output to the console indicates that the two values are equal
if abs (double1 - double2) <= difference then
printfn "double1 and double2 are equal."
else
printfn "double1 and double2 are unequal."
' Initialize two doubles with apparently identical values
Dim double1 As Double = .33333
Dim double2 As Double = 1/3
' Define the tolerance for variation in their values
Dim difference As Double = Math.Abs(double1 * .00001)
' Compare the values
' The output to the console indicates that the two values are equal
If Math.Abs(double1 - double2) <= difference Then
Console.WriteLine("double1 and double2 are equal.")
Else
Console.WriteLine("double1 and double2 are unequal.")
End If
Catatan
Karena Epsilon mendefinisikan ekspresi minimum dari nilai positif yang rentangnya mendekati nol, margin selisih antara dua nilai serupa harus lebih besar dari Epsilon. Biasanya, berkali-kali lebih besar dari Epsilon. Karena itu, kami sarankan Anda tidak menggunakan Epsilon saat membandingkan Double nilai untuk kesetaraan.
Teknik kedua melibatkan perbandingan perbedaan antara dua angka floating-point dengan beberapa nilai absolut. Jika perbedaannya kurang dari atau sama dengan nilai absolut tersebut, angkanya sama. Jika lebih besar, angkanya tidak sama. Salah satu alternatifnya adalah dengan memilih nilai absolut secara arbitrer. Namun, ini bermasalah karena margin perbedaan yang dapat diterima tergantung pada besarnya Double nilai. Alternatif kedua memanfaatkan fitur desain format floating-point: Perbedaan antara representasi bilangan bulat dari dua nilai floating-point menunjukkan jumlah kemungkinan nilai floating-point yang memisahkannya. Misalnya, perbedaan antara 0,0 dan Epsilon 1, karena Epsilon merupakan nilai terkecil yang dapat diwakili saat bekerja dengan nilainya nol Double . Contoh berikut menggunakan teknik ini untuk membandingkan .33333 dan 1/3, yang merupakan dua Double nilai contoh kode sebelumnya dengan metode yang Equals(Double) ditemukan tidak sama. Perhatikan bahwa contoh menggunakan BitConverter.DoubleToInt64Bits metode untuk mengonversi nilai floating-point presisi ganda ke representasi bilangan bulatnya.
using System;
public class Example
{
public static void Main()
{
double value1 = .1 * 10;
double value2 = 0;
for (int ctr = 0; ctr < 10; ctr++)
value2 += .1;
Console.WriteLine("{0:R} = {1:R}: {2}", value1, value2,
HasMinimalDifference(value1, value2, 1));
}
public static bool HasMinimalDifference(double value1, double value2, int units)
{
long lValue1 = BitConverter.DoubleToInt64Bits(value1);
long lValue2 = BitConverter.DoubleToInt64Bits(value2);
// If the signs are different, return false except for +0 and -0.
if ((lValue1 >> 63) != (lValue2 >> 63))
{
if (value1 == value2)
return true;
return false;
}
long diff = Math.Abs(lValue1 - lValue2);
if (diff <= (long) units)
return true;
return false;
}
}
// The example displays the following output:
// 1 = 0.99999999999999989: True
open System
let hasMinimalDifference (value1: double) (value2: double) (units: int) =
let lValue1 = BitConverter.DoubleToInt64Bits value1
let lValue2 = BitConverter.DoubleToInt64Bits value2
// If the signs are different, return false except for +0 and -0.
if (lValue1 >>> 63) <> (lValue2 >>> 63) then
value1 = value2
else
let diff = abs (lValue1 - lValue2)
diff <= int64 units
let value1 = 0.1 * 10.
let mutable value2 = 0.
for _ = 0 to 9 do
value2 <- value2 + 0.1
printfn $"{value1:R} = {value2:R}: {hasMinimalDifference value1 value2 1}"
// The example displays the following output:
// 1 = 0.99999999999999989: True
Module Example
Public Sub Main()
Dim value1 As Double = .1 * 10
Dim value2 As Double = 0
For ctr As Integer = 0 To 9
value2 += .1
Next
Console.WriteLine("{0:R} = {1:R}: {2}", value1, value2,
HasMinimalDifference(value1, value2, 1))
End Sub
Public Function HasMinimalDifference(value1 As Double, value2 As Double, units As Integer) As Boolean
Dim lValue1 As long = BitConverter.DoubleToInt64Bits(value1)
Dim lValue2 As long = BitConverter.DoubleToInt64Bits(value2)
' If the signs are different, Return False except for +0 and -0.
If ((lValue1 >> 63) <> (lValue2 >> 63)) Then
If value1 = value2 Then
Return True
End If
Return False
End If
Dim diff As Long = Math.Abs(lValue1 - lValue2)
If diff <= units Then
Return True
End If
Return False
End Function
End Module
' The example displays the following output:
' 1 = 0.99999999999999989: True
Presisi angka floating-point di luar presisi yang didokumentasikan khusus untuk implementasi dan versi .NET Framework. Akibatnya, perbandingan dua angka tertentu mungkin berubah antara versi .NET Framework karena presisi representasi internal angka mungkin berubah.
Jika dua Double.NaN nilai diuji untuk kesetaraan Equals dengan memanggil metode , metode mengembalikan true
. Namun, jika dua NaN nilai diuji untuk kesetaraan dengan menggunakan operator kesetaraan, operator mengembalikan false
. Ketika Anda ingin menentukan apakah nilai Double bukan angka (NaN), alternatifnya adalah memanggil IsNaN metode .
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk