`Vector <float> .Equals`는 반사적이어야합니까, 아니면 IEEE 754 의미론을 따라야합니까?


9

부동 소수점 값이 동일한 지 비교할 때 두 가지 접근 방식이 있습니다.

C # ( floatdouble) 에 내장 된 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, yznull이 아닌 객체 참조를 나타냅니다.

    x.Equals(x)true부동 소수점 유형과 관련된 경우를 제외하고는를 반환합니다 . ISO / IEC / IEEE 60559 : 2011, 정보 기술-마이크로 프로세서 시스템-부동 소수점 산술을 참조하십시오.

  • 플로트를 사전 키로 사용하는 경우 죄 상태에 살고 있으며 제정신의 행동을 기 대해서는 안됩니다.

재귀 적 주장 :

  • 그것은을 포함하여 기존의 유형과 일치의 Single, Double, TupleSystem.Numerics.Complex.

    나는 BCL에서 Equals재귀 대신 IEEE를 따르는 전례를 모른다 . 카운터 예는 Single, Double, TupleSystem.Numerics.Complex.

  • Equals주로 반사율에 의존하는 컨테이너 및 검색 알고리즘에서 사용됩니다. 이러한 알고리즘의 경우 작동을 방해하는 경우 성능 향상과 관련이 없습니다. 성능의 정확성을 희생하지 마십시오.
  • 그것은 모든 해시 기반 집합과 사전 파괴, Contains, Find, IndexOf다양한 수집 / LINQ, 집합 기반 LINQ 동작 (ON Union, Except등)의 데이터가 포함되어 있으면 NaN값.
  • IEEE 시맨틱이 허용되는 실제 계산을 수행하는 코드는 일반적으로 구체적인 유형에서 작동하며 ==/ !=또는 엡실론 비교를 사용합니다.

    현재 산술 연산이 필요하기 때문에 제네릭을 사용하여 고성능 계산을 작성할 수는 없지만 인터페이스 / 가상 방법으로는 사용할 수 없습니다.

    따라서 느린 Equals방법은 대부분의 고성능 코드에 영향을 미치지 않습니다.

  • IEEE 의미가 필요하거나 성능 이점이 필요한 경우를위한 IeeeEquals방법이나 방법 을 제공 IeeeEqualityComparer<T>할 수 있습니다.

제 생각에는 이러한 주장 은 재귀적인 구현을 강력하게 선호합니다.

Microsoft의 CoreFX 팀은 이러한 벡터 유형을 .NET에 도입 할 계획입니다. 저와 달리 그들은 주로 성능 이점 때문에 IEEE 솔루션을 선호합니다 . 최종 결정 이후에도 그러한 결정이 변경되지 않기 때문에, 나는 큰 실수라고 생각하는 것에 대해 커뮤니티로부터 피드백을 받고 싶습니다.


1
우수하고 생각을 자극하는 질문입니다. 나 (이상)의 경우, 이해가가되지 않습니다 ==Equals다른 결과를 반환합니다. 많은 프로그래머들이 있다고 가정하고 어떻게 같은 일을 . 게다가, 평등 연산자의 구현은 일반적으로 Equals메소드를 호출합니다 . 당신은 하나를 포함 할 수 있다고 주장 IeeeEquals했지만, 다른 방법으로 수행하고-방법을 포함 할 ReflexiveEquals수도 있습니다. Vector<float>형이 사용될 수있다 많은 성능 중요한 애플리케이션, 따라서 최적화되어야한다.
die maus

@diemaus 내가 그 설득력 찾을 수없는 몇 가지 이유 : 1) float/ double여러 다른 유형 ==Equals이미 다르다. 기존 유형 ==과 의 불일치가 Equals다른 유형 의 불일치보다 더 혼란 스럽다고 생각하며 여전히 다른 유형을 처리해야합니다. 2) 거의 모든 일반 알고리즘 / 컬렉션 Equals은 기능에 대한 반사성 (LINQ 및 사전)을 사용 하고 의존하지만, 구체적인 부동 소수점 알고리즘은 일반적으로 ==IEEE 의미를 얻는 곳에서 사용 합니다.
코드 InChaos

나는 Vector<float>단순한 float또는 다른 "짐승"을 고려할 것 double입니다. 그 측정으로 Equals==운영자가 표준을 준수해야하는 이유나 이유를 알 수 없습니다 . "수레를 사전 키로 사용하는 경우 죄의 상태에 처해 있고 제정신의 행동을 기 대해서는 안됩니다." 하나가 NaN사전 에 저장된다면 , 그것은 끔찍한 연습을 사용하는 것에 대한 자체의 잘못입니다. 나는 CoreFX 팀이 이것을 생각하지 않았다고 생각하지 않습니다. 나는 ReflexiveEquals성능을 위해서 또는 그와 비슷한 것을 갈 것입니다 .
die maus

답변:


5

나는 IEEE 행동이 옳다고 주장한다. NaNs는 어떤 식 으로든 서로 동등하지 않습니다. 숫자 답변이 적합하지 않은 잘못 정의 된 조건에 해당합니다.

대부분의 프로세서가 기본적으로 지원하는 IEEE 산술을 사용함으로써 얻을 수있는 성능상의 이점을 넘어 서면 isnan(x) && isnan(y), 그렇다면 이라는 의미 상 문제가 있다고 생각합니다 x == y. 예를 들어 :

// C++
double inf = std::numeric_limits<double>::infinity();
double x = 0.0 / 0.0;
double y = inf - inf;

나는 누군가가 x동등 하다고 생각하는 의미있는 이유가 없다고 주장합니다 y. 그것들이 동등한 숫자라고 결론 내릴 수는 없습니다. 그것들은 전혀 숫자가 아니기 때문에 완전히 잘못된 개념처럼 보입니다.

또한 API 디자인 관점에서 많은 프로그래머가 사용하도록 고안된 범용 라이브러리에서 작업하는 경우 가장 업계에서 가장 일반적인 부동 소수점 의미 체계를 사용하는 것이 좋습니다. 좋은 도서관의 목표는 도서관을 이용하는 사람들의 시간을 절약하는 것입니다.


3
NaN == NaN반환해야합니다 거짓은 타의 추종을 불허한다. 문제는 .Equals방법 이 무엇을 해야 하는가입니다. 예를 들어 NaN사전 키로 사용 하는 경우 NaN.Equals(NaN)false를 반환 하면 관련 값을 검색 할 수 없게됩니다 .
코드 InChaos

1
일반적인 경우에 맞게 최적화해야한다고 생각합니다. 숫자 벡터의 일반적인 경우는 높은 처리량 수치 계산 (종종 SIMD 명령으로 최적화)입니다. 벡터를 사전 키로 사용하는 것은 극히 드문 사용 사례이며 시맨틱을 디자인 할 가치가 거의 없습니다. 기존부터 나에게 가장 합리적인 것 같습니다 반론은 일관성이다 Single, Double등의 클래스가 이미 반사적 행동이있다. IMHO, 그것은 단지 잘못된 결정이었습니다. 그러나 나는 우아함이 유용성 / 속도를 방해하지 않도록 할 것입니다.
Jason R

그러나 수치 계산에는 일반적으로 ==항상 IEEE를 따르는 것이 사용 되므로 Equals구현 방법 에 관계없이 빠른 코드를 얻습니다 . IMO는 별도의 Equals방법을 사용하는 것이 LINQ의 Distinct()기능 과 같이 구체적인 유형에 신경 쓰지 않는 알고리즘에서 사용하고 있습니다.
코드 InChaos

1
나는 그것을 얻는다. 그러나 나는 의미가 다른 ==연산자와 Equals()함수 가있는 API에 대해 논쟁 할 것 입니다. 나는 당신이 개발자의 관점에서 잠재적 인 혼란없이 잠재적 인 혼란을 겪고 있다고 생각한다. 내 의견 일뿐입니다. 나는 그 질문에 대한 객관적인 대답이 없다고 생각합니다.
Jason R

0

문제가있다 : IEEE754는 수치 적 응용에 적합한 방식으로 관계 연산과 평등을 정의한다. 정렬 및 해싱에는 적합하지 않습니다. 따라서 숫자 값을 기준으로 배열을 정렬하거나 숫자 값을 집합에 추가하거나 사전에서 키로 사용하려면 NaN 값이 허용되지 않거나 IEEE754를 사용하지 않는다고 선언합니다 내장 작업. 해시 테이블은 모든 NaN이 동일한 값과 일치하는지 확인하고 서로 비교해야합니다.

Vector를 정의하면 숫자 목적으로 만 사용할지 또는 정렬 및 해싱과 호환되어야하는지 디자인 결정을 내려야합니다. 개인적으로 수치 적 목적이 훨씬 더 중요하다고 생각합니다. 정렬 / 해싱이 필요한 경우 Vector를 멤버로 사용하여 클래스를 작성하고 해당 클래스에서 원하는 방식으로 해싱과 동등성을 정의 할 수 있습니다.


1
수치 적 목적이 더 중요하다는 데 동의합니다. 그러나 우리는 이미 그들 ==!=연산자를 가지고 있습니다. 내 경험에 따르면이 Equals방법은 숫자가 아닌 알고리즘에서만 사용됩니다.
코드 InChaos
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.