Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Nota
Artikel ini menyediakan keterangan tambahan untuk dokumentasi referensi untuk API ini.
Metode Single.Equals(Single) mengimplementasikan antarmuka System.IEquatable<T>, dan berkinerja sedikit lebih baik daripada Single.Equals(Object) karena tidak harus mengonversi parameter obj menjadi objek.
Konversi meluas
Bergantung pada bahasa pemrograman Anda, mungkin untuk mengkodekan suatu metode Equals dengan jenis parameter yang memiliki jumlah bit lebih sedikit (lebih sempit) daripada jenis instance. Hal ini dimungkinkan karena beberapa bahasa pemrograman melakukan konversi pelebaran implisit yang mewakili parameter sebagai tipe dengan jumlah bit yang sama banyaknya dengan instans.
Misalnya, jenis instans Single dan jenis parameternya Int32. Pengkompilasi Microsoft C# menghasilkan instruksi untuk mewakili nilai parameter sebagai objek Single, lalu menghasilkan metode Single.Equals(Single) 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 Tabel Konversi Jenis .
Presisi dalam perbandingan
Metode Equals 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 nilai Single .3333 dan Single yang dikembalikan dengan membagi 1 dengan 3 tidak sama.
// Initialize two floats with apparently identical values
float float1 = .33333f;
float float2 = 1/3;
// Compare them for equality
Console.WriteLine(float1.Equals(float2)); // displays false
// Initialize two floats with apparently identical values
let float1 = 0.33333f
let float2 = 1f / 3f
// Compare them for equality
printfn $"{float1.Equals float2}" // displays false
' Initialize two singles with apparently identical values
Dim single1 As Single = .33333
Dim single2 As Single = 1/3
' Compare them for equality
Console.WriteLine(single1.Equals(single2)) ' displays False
Salah satu teknik perbandingan yang menghindari masalah yang terkait dengan perbandingan untuk kesetaraan melibatkan penentuan margin perbedaan yang dapat diterima antara dua nilai (seperti .01% salah satu nilai). Jika nilai absolut perbedaan antara kedua nilai kurang dari atau sama dengan margin tersebut, perbedaannya kemungkinan merupakan hasil dari perbedaan presisi dan, oleh karena itu, nilainya kemungkinan sama. Contoh berikut menggunakan teknik ini untuk membandingkan .33333 dan 1/3, yang merupakan dua nilai Single yang ditemukan contoh kode sebelumnya tidak sama.
// Initialize two floats with apparently identical values
float float1 = .33333f;
float float2 = (float) 1/3;
// Define the tolerance for variation in their values
float difference = Math.Abs(float1 * .0001f);
// Compare the values
// The output to the console indicates that the two values are equal
if (Math.Abs(float1 - float2) <= difference)
Console.WriteLine("float1 and float2 are equal.");
else
Console.WriteLine("float1 and float2 are unequal.");
// Initialize two floats with apparently identical values
let float1 = 0.33333f
let float2 = 1f / 3f
// Define the tolerance for variation in their values
let difference = abs (float1 * 0.0001f)
// Compare the values
// The output to the console indicates that the two values are equal
if abs (float1 - float2) <= difference then
printfn "float1 and float2 are equal."
else
printfn "float1 and float2 are unequal."
' Initialize two singles with apparently identical values
Dim single1 As Single = .33333
Dim single2 As Single = 1/3
' Define the tolerance for variation in their values
Dim difference As Single = Math.Abs(single1 * .0001f)
' Compare the values
' The output to the console indicates that the two values are equal
If Math.Abs(single1 - single2) <= difference Then
Console.WriteLine("single1 and single2 are equal.")
Else
Console.WriteLine("single1 and single2 are unequal.")
End If
Dalam hal ini, nilainya sama.
Nota
Karena Epsilon mendefinisikan ekspresi minimum nilai positif yang rentangnya mendekati nol, margin perbedaan harus lebih besar dari Epsilon. Biasanya, berkali-kali lebih besar dari Epsilon. Karena itu, kami sarankan Anda tidak menggunakan Epsilon saat membandingkan nilai Double untuk kesetaraan.
Teknik kedua yang menghindari masalah dalam membandingkan kesetaraan melibatkan perbandingan perbedaan antara dua angka floating-point dengan nilai absolut tertentu. Jika perbedaannya kurang dari atau sama dengan nilai absolut tersebut, angkanya sama. Jika lebih besar, angkanya tidak sama. Salah satu cara untuk melakukan ini adalah dengan memilih nilai absolut secara segan-segan. Namun, ini bermasalah, karena margin perbedaan yang dapat diterima tergantung pada besarnya nilai Single. Cara kedua memanfaatkan fitur desain format floating-point: Perbedaan antara komponen mantissa dalam representasi bilangan bulat dari dua nilai floating-point menunjukkan jumlah kemungkinan nilai floating-point yang memisahkan dua nilai. Misalnya, perbedaan antara 0,0 dan Epsilon adalah 1, karena Epsilon adalah nilai terkecil yang dapat diwakili saat bekerja dengan Single yang nilainya nol. Contoh berikut menggunakan teknik ini untuk membandingkan .33333 dan 1/3, yang merupakan dua nilai Double contoh kode sebelumnya dengan metode Equals(Single) yang ditemukan tidak sama. Perhatikan bahwa contoh menggunakan metode BitConverter.GetBytes dan BitConverter.ToInt32 untuk mengonversi nilai floating-point presisi tunggal ke representasi bilangan bulatnya.
using System;
public class Example
{
public static void Main()
{
float value1 = .1f * 10f;
float value2 = 0f;
for (int ctr = 0; ctr < 10; ctr++)
value2 += .1f;
Console.WriteLine($"{value1:R} = {value2:R}: {HasMinimalDifference(value1, value2, 1)}");
}
public static bool HasMinimalDifference(float value1, float value2, int units)
{
byte[] bytes = BitConverter.GetBytes(value1);
int iValue1 = BitConverter.ToInt32(bytes, 0);
bytes = BitConverter.GetBytes(value2);
int iValue2 = BitConverter.ToInt32(bytes, 0);
// If the signs are different, return false except for +0 and -0.
if ((iValue1 >> 31) != (iValue2 >> 31))
{
if (value1 == value2)
return true;
return false;
}
int diff = Math.Abs(iValue1 - iValue2);
if (diff <= units)
return true;
return false;
}
}
// The example displays the following output:
// 1 = 1.00000012: True
open System
let hasMinimalDifference (value1: float32) (value2: float32) units =
let bytes = BitConverter.GetBytes value1
let iValue1 = BitConverter.ToInt32(bytes, 0)
let bytes = BitConverter.GetBytes(value2)
let iValue2 = BitConverter.ToInt32(bytes, 0)
// If the signs are different, return false except for +0 and -0.
if (iValue1 >>> 31) <> (iValue2 >>> 31) then
value1 = value2
else
let diff = abs (iValue1 - iValue2)
diff <= units
let value1 = 0.1f * 10f
let value2 =
List.replicate 10 0.1f
|> List.sum
printfn $"{value1:R} = {value2:R}: {hasMinimalDifference value1 value2 1}"
// The example displays the following output:
// 1 = 1.0000001: True
Module Example
Public Sub Main()
Dim value1 As Single = .1 * 10
Dim value2 As Single = 0
For ctr As Integer = 0 To 9
value2 += CSng(.1)
Next
Console.WriteLine("{0:R} = {1:R}: {2}", value1, value2,
HasMinimalDifference(value1, value2, 1))
End Sub
Public Function HasMinimalDifference(value1 As Single, value2 As Single, units As Integer) As Boolean
Dim bytes() As Byte = BitConverter.GetBytes(value1)
Dim iValue1 As Integer = BitConverter.ToInt32(bytes, 0)
bytes = BitConverter.GetBytes(value2)
Dim iValue2 As Integer = BitConverter.ToInt32(bytes, 0)
' If the signs are different, Return False except for +0 and -0.
If ((iValue1 >> 31) <> (iValue2 >> 31)) Then
If value1 = value2 Then
Return True
End If
Return False
End If
Dim diff As Integer = Math.Abs(iValue1 - iValue2)
If diff <= units Then
Return True
End If
Return False
End Function
End Module
' The example displays the following output:
' 1 = 1.00000012: True
Presisi angka floating-point yang melebihi presisi terdokumentasi bergantung pada implementasi dan versi .NET. Akibatnya, perbandingan dua angka mungkin menghasilkan hasil yang berbeda tergantung pada versi .NET, karena presisi representasi internal angka mungkin berubah.