System.Double.Equals 메서드

Th Double.Equals(Double) 메서드는 인터페이스를 System.IEquatable<T> 구현하고 매개 변수를 개체로 변환 obj 할 필요가 없기 때문에 약간 더 잘 Double.Equals(Object) 수행됩니다.

확대 변환

프로그래밍 언어에 따라 매개 변수 형식이 인스턴스 형식보다 적은 비트(더 좁은) 메서드를 코딩 Equals 할 수 있습니다. 일부 프로그래밍 언어는 인스턴스만큼 많은 비트가 있는 형식으로 매개 변수를 나타내는 암시적 확대 변환을 수행하기 때문에 가능합니다.

예를 들어 인스턴스 형식이 Double 고 매개 변수 형식이 .입니다 Int32. Microsoft C# 컴파일러는 매개 변수의 값을 개체로 Double 나타내는 지침을 생성한 다음 인스턴스의 값과 매개 변수의 확장된 표현을 비교하는 메서드를 생성 Double.Equals(Double) 합니다.

프로그래밍 언어 설명서를 참조하여 컴파일러가 숫자 형식의 암시적 확대 변환을 수행하는지 확인합니다. 자세한 내용은 형식 변환 테이블 항목을 참조 하세요 .

비교의 정밀도

두 값의 Equals 전체 자릿수가 다르기 때문에 두 값이 동일하지 않을 수 있으므로 이 메서드는 주의해서 사용해야 합니다. 다음 예제에서는 .333333 값과 Double 1을 3으로 나누어 반환된 값이 같지 않음을 보고 Double 합니다.

// 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%)을 정의하는 작업이 포함됩니다. 두 값 간의 차이의 절대값이 해당 여백보다 작거나 같으면 정밀도 차이로 인해 차이가 발생할 수 있으므로 값이 같을 가능성이 높습니다. 다음 예제에서는 이 기술을 사용하여 이전 코드 예제에서 같지 않은 것으로 확인된 두 Double 값인 .33333과 1/3을 비교합니다. 이 경우 값은 같습니다.

// 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 범위가 0에 가까운 양수 값의 최소 식을 정의하므로 비슷한 두 값 사이의 차이 여백은 0보다 Epsilon커야 합니다. 일반적으로 .Epsilon 따라서 같음 값을 비교할 Double 때는 사용하지 Epsilon 않는 것이 좋습니다.

두 번째 기술에는 두 부동 소수점 숫자의 차이를 일부 절대값과 비교하는 작업이 포함됩니다. 차이가 절대값보다 작거나 같으면 숫자는 같습니다. 값이 크면 숫자가 같지 않습니다. 한 가지 대안은 임의로 절대값을 선택하는 것입니다. 그러나 허용되는 차이 여백은 값의 Double 크기에 따라 달라지므로 문제가 됩니다. 두 번째 대안은 부동 소수점 형식의 디자인 기능을 활용합니다. 두 부동 소수점 값의 정수 표현 간의 차이는 부동 소수점 값을 구분하는 가능한 부동 소수점 값의 수를 나타냅니다. 예를 들어 0.0과 Epsilon 1 사이의 차이는 값이 0인 작업 Double 시 가장 작은 표현 가능한 값이기 때문 Epsilon 입니다. 다음 예제에서는 이 기술을 사용하여 이전 코드 예제와 같지 않은 것으로 확인된 메서드의 두 Double 값인 .33333과 Equals(Double) 1/3을 비교합니다. 이 예제에서는 이 메서드를 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 버전 간에 두 개의 특정 숫자를 비교하면 변경될 수 있습니다.

메서드를 호출하여 두 Double.NaN 값이 같은지 테스트하면 메서드가 반환됩니다true.Equals 그러나 같음 연산자를 사용하여 두 NaN 값이 같은지 테스트하면 연산자가 반환됩니다 false. 값 Double 이 숫자(NaN)가 아닌지 확인하려는 경우 메서드를 호출 IsNaN 하는 것이 대안입니다.