부동 소수점 실수는 수를 정확히 표현할 수 없고 오차가 존재한다.
유니티나 언리얼 에디터에서 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 |