Make Unreal REAL.
article thumbnail
Published 2023. 1. 30. 10:23
실수를 비교하는 방법 C++/기타

 

부동 소수점 실수는 수를 정확히 표현할 수 없고 오차가 존재한다.

 

유니티나 언리얼 에디터에서 1이었던 값이 0.99999로 바뀌어 있는 걸 본 적이 있을 것이다.

 

따라서 실수가 같은지 비교하는 것은 사실 그리 간단하지 않다.

 

대략 같다.

// 절댓값(a - b) <= 절댓값이 크다고 추측되는 수 * Epsilon
bool approximatelyEqual(float a, float b)
{
    return fabs(a - b) <= (fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * EPSILON;
}

 

본질적으로 같다.

// 절댓값(a - b) <= 절댓값이 작다고 추측되는 수 * Epsilon
bool essentiallyEqual(float a, float b)
{
    return fabs(a - b) <= (fabs(a) > fabs(b) ? fabs(b) : fabs(a)) * EPSILON;
}

 

명확하게 크다.

// a - b > 절댓값이 크다고 추측되는 수 * Epsilon
bool definitelyGreaterThan(float a, float b)
{
    return (a - b) > (fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * EPSILON;
}

 

명확하게 작다.

// b - a > 절댓값이 크다고 추측되는 수 * Epsilon
bool definitelyLessThan(float a, float b)
{
    return (b - a) > (fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * EPSILON;
}

 

예시

 

#include <iostream>
#include <limits>

#define EPSILON numeric_limits<float>::epsilon()

using namespace std;

// 절댓값(a - b) <= 절댓값이 크다고 추측되는 수 * Epsilon
bool approximatelyEqual(float a, float b)
{
    return fabs(a - b) <= (fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * EPSILON;
}

// 절댓값(a - b) <= 절댓값이 작다고 추측되는 수 * Epsilon
bool essentiallyEqual(float a, float b)
{
    return fabs(a - b) <= (fabs(a) > fabs(b) ? fabs(b) : fabs(a)) * EPSILON;
}

// a - b > 절댓값이 크다고 추측되는 수 * Epsilon
bool definitelyGreaterThan(float a, float b)
{
    return (a - b) > (fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * EPSILON;
}

// b - a > 절댓값이 크다고 추측되는 수 * Epsilon
bool definitelyLessThan(float a, float b)
{
    return (b - a) > (fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * EPSILON;
}

int main(int argc, char* argv[])
{
    float a = 5.0, b = 5.0;

    cout << "approximatelyEqual(" << a << ", " << b << "): " << boolalpha << approximatelyEqual(a, b) << endl << endl;
    cout << "essentiallyEqual(" << a << ", " << b << "): " << boolalpha << essentiallyEqual(a, b) << endl << endl;
    cout << "definitelyGreaterThan(" << a << ", " << b << "): " << boolalpha << definitelyGreaterThan(a, b) << endl << endl;
    cout << "definitelyLessThan(" << a << ", " << b << "): " << boolalpha << definitelyLessThan(a, b) << endl << endl;

    a = 5.00001; b = 5.00002;

    cout << "approximatelyEqual(" << a << ", " << b << "): " << boolalpha << approximatelyEqual(a, b) << endl << endl;
    cout << "essentiallyEqual(" << a << ", " << b << "): " << boolalpha << essentiallyEqual(a, b) << endl << endl;
    cout << "definitelyGreaterThan(" << a << ", " << b << "): " << boolalpha << definitelyGreaterThan(a, b) << endl << endl;
    cout << "definitelyLessThan(" << a << ", " << b << "): " << boolalpha << definitelyLessThan(a, b) << endl << endl;

    return 0;
}

 

출력

approximatelyEqual(5, 5): true

essentiallyEqual(5, 5): true

definitelyGreaterThan(5, 5): false

definitelyLessThan(5, 5): false

approximatelyEqual(5.00001, 5.00002): false

essentiallyEqual(5.00001, 5.00002): false

definitelyGreaterThan(5.00001, 5.00002): false

definitelyLessThan(5.00001, 5.00002): true

'C++ > 기타' 카테고리의 다른 글

배열의 크기를 확인할 때 주의할 점  (0) 2023.02.13
디폴트 매개변수(Default Parameter)  (0) 2023.01.30
람다 식(Lambda expression)  (0) 2023.01.21
펑터(Functor)  (0) 2023.01.21
템플릿(Template)  (0) 2023.01.20
profile

Make Unreal REAL.

@diesuki4

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

검색 태그