부동 소수점 숫자가 평등을 위해 비교 될 수 없다는 일반적인 지혜는 부정확합니다. 부동 소수점 숫자는 정수와 다르지 않습니다. "a == b"로 평가하면 숫자가 같으면 true가되고 그렇지 않으면 false가됩니다 (두 개의 NaN은 물론 동일하지 않음).
실제 문제는 이것입니다 : 계산을했는데 비교 해야하는 두 숫자가 정확히 맞는지 확실하지 않으면 어떻게됩니까? 이 문제는 정수에서와 같이 부동 소수점에서 동일합니다. 정수 식 "7 / 3 * 3"을 평가하면 "7 * 3 / 3"과 같지 않습니다.
"정수와 정수를 어떻게 비교합니까?" 그런 상황에서. 단일 답변이 없습니다. 수행해야 할 작업은 특정 상황, 특히 어떤 종류의 오류 및 달성하려는 항목에 따라 다릅니다.
가능한 선택 사항은 다음과 같습니다.
수학적으로 정확한 숫자가 같으면 "진정한"결과를 얻으려면 수행하는 계산의 속성을 사용하여 두 숫자에서 동일한 오류가 발생 함을 증명할 수 있습니다. 이것이 가능하고 정확하게 계산 된 경우 동일한 숫자를 제공하는 표현식의 결과 인 두 숫자를 비교하면 비교에서 "참"이됩니다. 또 다른 방법은 계산의 속성을 분석하고 오류가 절대량 또는 입력 중 하나 또는 출력 중 하나에 상대적인 양을 절대 초과하지 않음을 증명할 수 있다는 것입니다. 이 경우 계산 된 두 숫자가 최대량만큼 다른지 물어보고 해당 간격 내에 있으면 "true"를 반환 할 수 있습니다. 에러 바운드를 증명할 수 없다면 당신은 추측하고 최선을 다하겠습니다. 추측하는 한 가지 방법은 많은 무작위 표본을 평가하고 결과에 어떤 종류의 분포가 있는지 확인하는 것입니다.
물론 수학적으로 정확한 결과가 같으면 "참"이라는 요구 사항 만 설정하기 때문에 결과가 같지 않아도 "참"이 될 가능성을 열어 두었습니다. (실제로 항상 "true"를 반환하여 요구 사항을 충족 할 수 있습니다. 이렇게하면 계산이 간단 해지지 만 일반적으로 바람직하지 않으므로 아래 상황 개선에 대해 논의하겠습니다.)
수학적으로 정확한 숫자가 다른 경우 "거짓"결과를 얻으려면 수학적으로 정확한 숫자가 다른 경우 숫자를 평가하면 다른 숫자가 생성됨을 증명해야합니다. 이것은 많은 일반적인 상황에서 실제적인 목적으로는 불가능할 수 있습니다. 대안을 생각해 봅시다.
수학적으로 정확한 숫자가 일정량 이상 차이가 나는 경우 "거짓"결과를 얻는 것이 유용한 요구 사항 일 수 있습니다. 예를 들어, 컴퓨터 게임에서 던진 공이 어디로 갔는지 계산할 것이며 공이 타격을 받았는지 알고 싶을 것입니다. 이 경우, 공이 방망이에 부딪히면 반드시 "참"을 원하고, 공이 방망이에서 멀어지면 "거짓"을하려고합니다. 수학적으로 정확한 시뮬레이션은 박쥐를 놓쳤지만 박쥐를 때리는 밀리미터 이내에 있습니다. 이 경우, 볼의 위치와 타석의 위치 계산시 최대 1 밀리미터 (모든 관심 위치에 대한)의 결합 오차가 있음을 증명 (또는 추측 / 추정)해야합니다. 이렇게하면 항상 "
따라서 부동 소수점 숫자를 비교할 때 반환 할 항목을 결정하는 방법은 특정 상황에 따라 크게 다릅니다.
계산에 대한 오류 범위를 증명하는 방법에 대해서는 복잡한 주제가 될 수 있습니다. 가장 가까운 반올림 모드에서 IEEE 754 표준을 사용하는 부동 소수점 구현은 기본 연산 (특히 곱셈, 나눗셈, 덧셈, 뺄셈, 제곱근)에 대한 정확한 결과에 가장 가까운 부동 소수점 숫자를 반환합니다. (동점의 경우, 라운드가 낮으므로 라운드 비트가 고르게됩니다.) (제곱근과 나눗셈에 특히주의하십시오. 언어 구현은 IEEE 754를 준수하지 않는 메소드를 사용할 수 있습니다.)이 요구 사항 때문에 단일 결과의 오류는 최하위 비트 값의 최대 1/2입니다. (더 많으면 반올림은 값의 1/2 내에있는 다른 숫자로 넘어 갔을 것입니다.)
거기에서 나아가는 것은 훨씬 더 복잡해진다. 다음 단계는 입력 중 하나에 이미 오류가있는 작업을 수행하는 것입니다. 간단한 표현식의 경우, 이러한 오류는 계산을 통해 최종 오류에 대한 경계에 도달 할 수 있습니다. 실제로 이것은 고품질 수학 라이브러리 작업과 같은 몇 가지 상황에서만 수행됩니다. 물론 어떤 작업이 수행되는지 정확하게 제어해야합니다. 고급 언어는 종종 컴파일러에게 많은 여유를 주므로 어떤 순서로 작업이 수행되는지 알 수 없습니다.
이 주제에 관해 쓰여질 수있는 것이 더 많지만 여기서 멈추어야합니다. 요약하면 답은 다음과 같습니다. 라이브러리 루틴에 넣을 가치가있는 대부분의 요구에 맞는 단일 솔루션이 없기 때문에이 비교에는 라이브러리 루틴이 없습니다. (상대 또는 절대 오류 간격과 비교하면 충분하므로 라이브러리 루틴없이 간단하게 수행 할 수 있습니다.)