System.Double.Equals 方法

此方法 Double.Equals(Double) 會實作 System.IEquatable<T> 介面,而且執行效能會稍微 Double.Equals(Object) 好一些,因為它不需要將 obj 參數轉換成 物件。

擴大轉換

視您的程式設計語言而定,可能會撰寫方法的程序代碼 Equals ,其中參數類型比實例類型少一些(較窄)。 這是可能的,因為某些程式設計語言會執行隱含擴大轉換,將參數表示為具有實例數目之位的類型。

例如,假設實體類型為 Double ,且參數類型為 Int32。 Microsoft C# 編譯程式會產生指示,將參數的值表示為 Double 對象,然後產生 Double.Equals(Double) 方法,以比較 實例的值和參數的擴大表示法。

請參閱程式設計語言的檔,以判斷其編譯程式是否執行數值類型的隱含擴大轉換。 如需詳細資訊,請參閱 類型轉換數據表 主題。

比較的有效位數

Equals方法應該謹慎使用,因為兩個明顯相等的值可能會因為兩個值的不同精確度而不相等。 下列範例會報告 Double 值 .333333和 Double 除以 1 乘以 3 所傳回的值不相等。

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

一種技術不需要比較相等,而是定義兩個值之間可接受的相對差距(例如其中一個值的 .001% )。 如果兩個值之間的差異絕對值小於或等於該邊界,則差異可能是由於有效位數的差異,因此,這些值可能會相等。 下列範例會使用這項技術來比較 .33333 和 1/3,前 Double 一個程式代碼範例發現兩個值不相等。 在此情況下,值相等。

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

注意

由於 Epsilon 定義範圍接近零之正值的最小運算式,因此兩個相似值之間的差異邊界必須大於 Epsilon。 一般而言,其大於 Epsilon的倍數。 因此,建議您不要在比較Double相等值時使用 Epsilon

第二種技術涉及比較兩個浮點數與某些絕對值之間的差異。 如果差異小於或等於該絕對值,數位就會相等。 如果大於,則數位不相等。 其中一個替代方法是任意選取絕對值。 不過,這是有問題的,因為可接受的差異邊界取決於值的大小 Double 。 第二個替代方法會利用浮點格式的設計功能:兩個浮點值的整數表示之間的差異表示可能分隔它們的浮點值數目。 例如,0.0 和 Epsilon 1 之間的差異,因為 Epsilon 使用值為零的 時 Double ,是最小可表示的值。 下列範例會使用這項技術來比較 .33333 和 1/3,這是上一個程式代碼範例Equals(Double)與方法不相等的兩Double個值。 請注意,此範例會使用 BitConverter.DoubleToInt64Bits 方法,將雙精確度浮點值轉換成其整數表示法。

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

超出記載有效位數的浮點數有效位數是 .NET Framework 的實作和版本特有的。 因此,兩個特定數字的比較可能會在 .NET Framework 的版本之間變更,因為數字的內部表示精確度可能會變更。

如果呼叫 方法測試Equals兩個Double.NaN值是否相等,則 方法會傳true回 。 不過,如果使用等號運算子測試兩個 NaN 值是否相等,運算符會傳 false回 。 當您想要判斷 的值是否 Double 不是數位 (NaN),替代方法是呼叫 IsNaN 方法。