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 使用 方法,將雙精確度浮點值轉換為其整數表示法。 如果整數表示法之間沒有可能的浮點值,則此範例會將值宣告為相等。
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
注意
對於某些值,即使整數表示法之間有可能的浮點值,您仍可能會將其視為相等。 例如,請考慮雙精度浮點數 0.39
和 1.69 - 1.3
(計算為 0.3899999999999999
)。 在小端電腦上,這些值的整數表示分別為 4600697235336603894
和 4600697235336603892
。 整數值之間的差異是 2
,這表示 和 1.69 - 1.3
之間0.39
有可能的浮點值。
版本差異
超出記載有效位數的浮點數有效位數是實作和 .NET 版本特有的。 因此,兩個特定數字的比較可能會在 .NET 版本之間變更,因為數位的內部表示精確度可能會變更。
NaN
如果呼叫 方法測試Equals兩個Double.NaN值是否相等,則 方法會傳true
回 。 不過,如果使用等號運算子測試兩個Double.NaN值是否相等,運算符會傳false
回 。 當您想要判斷 的值是否 Double 不是數位 (NaN),替代方法是呼叫 IsNaN 方法。