System.Single.Equals yöntemi

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

Single.Equals(Single) yöntemi arabirimini uygular ve parametresini System.IEquatable<T> bir nesneye dönüştürmesi obj gerekmediğinden biraz daha iyi Single.Equals(Object) performans gösterir.

Dönüştürmeleri genişletme

Programlama dilinize bağlı olarak, parametre türünün örnek türünden daha az bit (daha dar) olduğu bir Equals yöntem kodlayabilirsiniz. Bazı programlama dilleri parametreyi bitler örnek kadar çokmuş gibi bir tür olarak temsil eden dolaylı bir genişletme dönüşümü gerçekleştirdiği için bu olasıdır.

Örneğin, örnek türünün ve Single parametre türünün olduğunu Int32varsayalım. Microsoft C# derleyicisi parametrenin değerini nesne Single olarak temsil eden yönergeler oluşturur ve ardından örneğin değerlerini ve parametrenin geniş gösterimini karşılaştıran bir Single.Equals(Single) yöntem oluşturur.

Programlama dilinizle ilgili belgelere bakarak; derleyicisinin, sayısal türlere ilişkin örtülü genişletme dönüştürmeleri yapıp yapmadığını belirleyin. Daha fazla bilgi için bkz . Tür Dönüştürme Tabloları.

Karşılaştırmalarda duyarlık

yöntemi Equals dikkatli kullanılmalıdır, çünkü iki değerin farklı duyarlığı nedeniyle eşit olmayan iki eşdeğer değer olabilir. Aşağıdaki örnek, .3333 değerinin SingleSingle ve 1'i 3'e bölerek döndürülen değerinin eşit olmadığını bildirir.

// 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

Eşitlik karşılaştırmasıyla ilgili sorunlardan kaçınan bir karşılaştırma tekniği, iki değer arasında kabul edilebilir bir fark marjı tanımlamayı içerir (örneğin, değerlerden birinin %01'i). İki değer arasındaki farkın mutlak değeri bu kenar boşluğundan küçük veya buna eşitse, fark büyük olasılıkla duyarlık farklılıklarının sonucudur ve bu nedenle değerlerin eşit olması muhtemeldir. Aşağıdaki örnek, önceki kod örneğinin eşit olmadığını bulduğu iki Single değer olan .33333 ve 1/3'leri karşılaştırmak için bu tekniği kullanır.

// 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

Bu durumda değerler eşittir.

Not

Aralığı sıfıra yakın olan pozitif bir değerin minimum ifadesini tanımladığından Epsilon , farkın kenar boşluğu değerinden Epsilonbüyük olmalıdır. Genellikle, değerinden çok daha Epsilonbüyüktür. Bu nedenle, eşitlik için değerleri karşılaştırırken Double kullanmamanızı Epsilon öneririz.

Eşitlik karşılaştırmasıyla ilgili sorunlardan kaçınan ikinci bir teknik, iki kayan noktalı sayı arasındaki farkın mutlak bir değerle karşılaştırılmasını içerir. Fark bu mutlak değerden küçük veya buna eşitse, sayılar eşittir. Daha büyükse, sayılar eşit değildir. Bunu yapmanızın bir yolu, rastgele bir mutlak değer seçmektir. Ancak, kabul edilebilir bir fark marjı değerlerin büyüklüğüne Single bağlı olduğundan bu sorun yaratır. İkinci bir yol kayan nokta biçiminin tasarım özelliğinden yararlanır: İki kayan nokta değerinin tamsayı gösterimlerindeki mantis bileşenleri arasındaki fark, iki değeri ayıran olası kayan nokta değerlerinin sayısını gösterir. Örneğin, 0,0 ile Epsilon 1 arasındaki farktır, çünkü Epsilon değeri sıfır olan bir Single değerle çalışırken en küçük temsil edilebilir değerdir. Aşağıdaki örnek, önceki kod örneğinin yöntemle eşit olmadığını bulduğu iki Double değer olan .33333 ve Equals(Single) 1/3'leri karşılaştırmak için bu tekniği kullanır. Örnekte tek duyarlıklı kayan BitConverter.GetBytes nokta değerini tamsayı gösterimine dönüştürmek için ve BitConverter.ToInt32 yöntemlerinin kullanıldığına dikkat edin.

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("{0:R} = {1:R}: {2}", value1, value2,
                        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

Kayan noktalı sayıların, belgelenen duyarlığı aşan duyarlığı, .NET'in uygulamasına ve sürümüne özgüdür. Sonuç olarak, iki sayının karşılaştırması .NET sürümüne bağlı olarak farklı sonuçlar verebilir, çünkü sayıların iç gösteriminin duyarlığı değişebilir.