System.Single.Equals 메서드

이 문서에서는 이 API에 대한 참조 설명서에 대한 추가 설명서를 제공합니다.

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

확대 변환

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

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

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

비교의 정밀도

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

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

같음 비교와 관련된 문제를 방지하는 한 가지 비교 기술에는 두 값 간의 허용되는 차이 여백(예: 값 중 하나의 .01%)을 정의하는 작업이 포함됩니다. 두 값 간의 차이의 절대값이 해당 여백보다 작거나 같으면 이 차이는 정밀도 차이의 결과일 수 있으므로 값이 같을 가능성이 높습니다. 다음 예제에서는 이 기술을 사용하여 이전 코드 예제에서 같지 않은 것으로 확인된 두 Single 값인 .33333과 1/3을 비교합니다.

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

이 경우 값은 같습니다.

참고 항목

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

같음 비교와 관련된 문제를 방지하는 두 번째 기술은 두 부동 소수점 숫자 간의 차이를 절대값과 비교하는 것입니다. 차이가 절대값보다 작거나 같으면 숫자는 같습니다. 값이 크면 숫자가 같지 않습니다. 이 작업을 수행하는 한 가지 방법은 임의로 절대값을 선택하는 것입니다. 그러나 허용되는 차이의 여백은 값의 Single 크기에 따라 달라지므로 문제가 됩니다. 두 번째 방법은 부동 소수점 형식의 디자인 기능을 활용합니다. 두 부동 소수점 값의 정수 표현에서 가수 구성 요소 간의 차이는 두 값을 구분하는 가능한 부동 소수점 값의 수를 나타냅니다. 예를 들어 0.0과 Epsilon 1 사이의 차이는 값이 0인 작업 Single 시 가장 작은 표현 가능한 값이기 때문 Epsilon 입니다. 다음 예제에서는 이 기술을 사용하여 이전 코드 예제와 같지 않은 것으로 확인된 메서드의 두 Double 값인 .33333과 Equals(Single) 1/3을 비교합니다. 이 예제에서는 단정밀도 부동 소수점 값을 정수 표현으로 변환하기 위해 메서드와 BitConverter.ToInt32 메서드를 사용합니다BitConverter.GetBytes.

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

문서화된 전체 자릿수를 초과하는 부동 소수점 숫자의 정밀도는 .NET의 구현 및 버전과 관련이 있습니다. 따라서 두 숫자를 비교하면 숫자의 내부 표현 정밀도가 변경될 수 있으므로 .NET 버전에 따라 다른 결과가 생성될 수 있습니다.