Aracılığıyla paylaş


System.Double.Equals yöntemi

Double.Equals(Double) yöntemi System.IEquatable<T> arabirimini uygular ve Double.Equals(Object) parametresini bir nesneye dönüştürmesi gerekmediği için obj yönteminden biraz daha iyi 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, örneğin sahip olduğu bit sayısı kadar bit içeren bir tür olarak temsil eden örtük bir genişletme dönüşümü gerçekleştirdiği için bu mümkündür.

Örneğin, örnek türü Double ve parametre türü Int32 olsun. Microsoft C# derleyicisi, parametrenin değerini nesne Double olarak göstermek için yönergeler oluşturur, ardından örneğin değerlerini ve parametrenin geniş gösterimini karşılaştıran bir Double.Equals(Double) 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 Tür Dönüştürme Tabloları konusuna bakın.

Karşılaştırmalarda kesinlik

Equals yöntemi dikkatli bir şekilde kullanılmalıdır, çünkü iki görünüşte eşdeğer olan değer, farklı duyarlık nedeniyle eşit olmayabilir. Aşağıdaki örnek, .333333 değerinin Double ve 1'i 3'e bölerek döndürülen değerin eşit olmadığını bildirirDouble.

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

Bir teknik, eşitlik karşılaştırması yerine iki değer arasındaki kabul edilebilir göreli fark marjını tanımlamayı içerir (örneğin, değerlerden birinin %0,001'i). İki değer arasındaki farkın mutlak değeri bu kenar boşluğundan küçük veya buna eşitse, farkın büyük olasılıkla duyarlık farklılıkları ve dolayısıyla değerlerin eşit olması muhtemeldir. Aşağıdaki örnek, önceki kod örneğinin eşit olmadığını bulduğu iki Double değer olan .33333 ve 1/3 değerlerini karşılaştırmak için bu tekniği kullanır. Bu durumda değerler eşittir.

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

Not

Aralığı sıfıra yakın olan pozitif bir değerin minimum ifadesini tanımladığından Epsilon , benzer iki değer arasındaki farkın kenar boşluğu değerinden Epsilonbüyük olmalıdır. Genellikle, Epsilon'nin katları kadar büyüktür. Bu nedenle, eşitlik için değerleri karşılaştırırken kullanmamanızı EpsilonDouble öneririz.

İkinci 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. Alternatiflerden biri, rastgele bir mutlak değer seçmektir. Ancak bu sorun yaratır çünkü kabul edilebilir bir fark marjı değerlerin büyüklüğüne Double bağlıdır. İkinci bir alternatif, kayan nokta biçiminin tasarım özelliğinden yararlanır: İki kayan nokta değerinin tamsayı gösterimi arasındaki fark, bunları 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 Double 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(Double) 1/3'leri karşılaştırmak için bu tekniği kullanır. Örnek, çift hassasiyetli kayan nokta değerini tamsayı gösterimine dönüştürmek için BitConverter.DoubleToInt64Bits yöntemini kullanır. Örnek, tamsayı gösterimleri arasında olası kayan nokta değerleri yoksa değerleri eşit olarak bildirir.

public static void Main()
{
    // Initialize the values.
    double value1 = .1 * 10;
    double value2 = 0;
    for (int ctr = 0; ctr < 10; ctr++)
        value2 += .1;

    Console.WriteLine($"{value1:R} = {value2:R}: " +
        $"{HasMinimalDifference(value1, value2, 1)}");
}

public static bool HasMinimalDifference(
    double value1,
    double value2,
    int allowableDifference
    )
{
    // Convert the double values to long values.
    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;
    }

    // Calculate the number of possible
    // floating-point values in the difference.
    long diff = Math.Abs(lValue1 - lValue2);

    if (diff <= allowableDifference)
        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

Not

Bazı değerler için, tamsayı gösterimleri arasında olası bir kayan nokta değeri olsa bile bunları eşit olarak düşünebilirsiniz. Örneğin, 0.39 ve 1.69 - 1.3 (bu 0.3899999999999999 olarak hesaplanır) çift değerlerini göz önünde bulundurun. Küçük uçlu bir bilgisayarda, bu değerlerin tamsayı gösterimleri sırasıyla 4600697235336603894 ve 4600697235336603892'dir. Tamsayı değerleri arasındaki fark , 2ile arasında 0.39 olası bir kayan nokta değeri olduğu1.69 - 1.3anlamına gelir.

Sürüm farklılıkları

Kayan noktalı sayıların, belgelenen duyarlığı aşan duyarlığı, .NET'in uygulamasına ve sürümüne özgüdür. Sonuç olarak, sayıların iç gösteriminin duyarlığı değişebileceğinden, belirli iki sayının karşılaştırması .NET sürümleri arasında değişebilir.

Nan

Eğer iki Double.NaN değeri, Equals yöntemi çağrılarak eşitlik açısından test edilirse, yöntem true değerini döndürür. Ancak, iki Double.NaN değer eşitlik işleci kullanılarak eşitlik için test edilirse, işleç döndürürfalse. Bir Double değerinin sayı (NaN) olup olmadığını belirlemek istediğinizde, alternatif yöntem IsNaN metodunu çağırmaktır.