부동 소수점 값이 동일한 지 비교할 때 두 가지 접근 방식이 있습니다.
C # ( float
및 double
) 에 내장 된 IEEE 부동 소수점 유형은 ==
및 !=
(및 같은 관계 연산자 <
)에 대한 IEEE 의미를 따르지만 object.Equals
, IEquatable<T>.Equals
(및 CompareTo
)에 대한 반사성을 보장 합니다.
이제 float
/ 위에 벡터 구조체를 제공하는 라이브러리를 고려하십시오 double
. 이러한 벡터 과부하 것이다 타입 ==
/ !=
및 재정 object.Equals
/ IEquatable<T>.Equals
.
무엇 모두에 동의하는 것은 즉 ==
/ !=
IEEE 의미를 따라야합니다. 문제는 그러한 라이브러리 Equals
가 반사성 또는 IEEE 의미와 일치하는 방식으로 (등식 연산자와 분리 된) 메소드를 구현해야하는지 입니다.
IEEE 시맨틱을 사용하기위한 인수 Equals
:
- IEEE 754에 따릅니다
SIMD 명령을 활용할 수 있기 때문에 (아마도) 빠릅니다.
SIMD 명령을 사용하여 반사 평등을 표현하는 방법과 성능 영향에 대한 스택 오버플로에 대한 별도의 질문을 했습니다. 부동 소수점 평등 비교를위한 SIMD 명령
업데이트 : 세 개의 SIMD 명령을 사용하여 반사 평등을 효율적으로 구현할 수있는 것처럼 보입니다.
Equals
부동 소수점을 포함 할 때 의 설명서 에는 반사성이 필요하지 않습니다.Equals (Object) 메소드의 모든 구현에 대해 다음 명령문이 적용되어야합니다. 목록에서
x
,y
및z
null이 아닌 객체 참조를 나타냅니다.x.Equals(x)
true
부동 소수점 유형과 관련된 경우를 제외하고는를 반환합니다 . ISO / IEC / IEEE 60559 : 2011, 정보 기술-마이크로 프로세서 시스템-부동 소수점 산술을 참조하십시오.플로트를 사전 키로 사용하는 경우 죄 상태에 살고 있으며 제정신의 행동을 기 대해서는 안됩니다.
재귀 적 주장 :
그것은을 포함하여 기존의 유형과 일치의
Single
,Double
,Tuple
와System.Numerics.Complex
.나는 BCL에서
Equals
재귀 대신 IEEE를 따르는 전례를 모른다 . 카운터 예는Single
,Double
,Tuple
와System.Numerics.Complex
.Equals
주로 반사율에 의존하는 컨테이너 및 검색 알고리즘에서 사용됩니다. 이러한 알고리즘의 경우 작동을 방해하는 경우 성능 향상과 관련이 없습니다. 성능의 정확성을 희생하지 마십시오.- 그것은 모든 해시 기반 집합과 사전 파괴,
Contains
,Find
,IndexOf
다양한 수집 / LINQ, 집합 기반 LINQ 동작 (ONUnion
,Except
등)의 데이터가 포함되어 있으면NaN
값. IEEE 시맨틱이 허용되는 실제 계산을 수행하는 코드는 일반적으로 구체적인 유형에서 작동하며
==
/!=
또는 엡실론 비교를 사용합니다.현재 산술 연산이 필요하기 때문에 제네릭을 사용하여 고성능 계산을 작성할 수는 없지만 인터페이스 / 가상 방법으로는 사용할 수 없습니다.
따라서 느린
Equals
방법은 대부분의 고성능 코드에 영향을 미치지 않습니다.IEEE 의미가 필요하거나 성능 이점이 필요한 경우를위한
IeeeEquals
방법이나 방법 을 제공IeeeEqualityComparer<T>
할 수 있습니다.
제 생각에는 이러한 주장 은 재귀적인 구현을 강력하게 선호합니다.
Microsoft의 CoreFX 팀은 이러한 벡터 유형을 .NET에 도입 할 계획입니다. 저와 달리 그들은 주로 성능 이점 때문에 IEEE 솔루션을 선호합니다 . 최종 결정 이후에도 그러한 결정이 변경되지 않기 때문에, 나는 큰 실수라고 생각하는 것에 대해 커뮤니티로부터 피드백을 받고 싶습니다.
float
/ double
여러 다른 유형 ==
과 Equals
이미 다르다. 기존 유형 ==
과 의 불일치가 Equals
다른 유형 의 불일치보다 더 혼란 스럽다고 생각하며 여전히 다른 유형을 처리해야합니다. 2) 거의 모든 일반 알고리즘 / 컬렉션 Equals
은 기능에 대한 반사성 (LINQ 및 사전)을 사용 하고 의존하지만, 구체적인 부동 소수점 알고리즘은 일반적으로 ==
IEEE 의미를 얻는 곳에서 사용 합니다.
Vector<float>
단순한 float
또는 다른 "짐승"을 고려할 것 double
입니다. 그 측정으로 Equals
는 ==
운영자가 표준을 준수해야하는 이유나 이유를 알 수 없습니다 . "수레를 사전 키로 사용하는 경우 죄의 상태에 처해 있고 제정신의 행동을 기 대해서는 안됩니다." 하나가 NaN
사전 에 저장된다면 , 그것은 끔찍한 연습을 사용하는 것에 대한 자체의 잘못입니다. 나는 CoreFX 팀이 이것을 생각하지 않았다고 생각하지 않습니다. 나는 ReflexiveEquals
성능을 위해서 또는 그와 비슷한 것을 갈 것입니다 .
==
와Equals
다른 결과를 반환합니다. 많은 프로그래머들이 있다고 가정하고 어떻게 같은 일을 . 게다가, 평등 연산자의 구현은 일반적으로Equals
메소드를 호출합니다 . 당신은 하나를 포함 할 수 있다고 주장IeeeEquals
했지만, 다른 방법으로 수행하고-방법을 포함 할ReflexiveEquals
수도 있습니다.Vector<float>
형이 사용될 수있다 많은 성능 중요한 애플리케이션, 따라서 최적화되어야한다.