부동소수점 비교

김펭귄·2025년 7월 21일

C++

목록 보기
7/20

부동소수점 비교의 한계

    if (0.3 == 0.1 + 0.2)
        std::cout << "equal";
    else 
		std::cout << "not equal";	// not equal 출력
  • 소수의 계산이나 소수에서의 형변환에서는 그 과정에서 값의 변동이 생길 수 있음
  • 소수값을 정확히 저장하지 못해, 대소비교(=,>)에 한계가 있다

비교 가능한 상황

  • 단, 계산식 없는 단순 float point literal의 경우에는 비교 가능하다(자료형도 동일할 경우)
if (foo() == 0.0) // foo()가 0.0을 리터럴로 반환할 경우

constexpr double gravity { 9.8 };
if (gravity == 9.8) 	// 리터럴로 초기화 했으므로 가능
if (gravity == 9.8f) 	// 자료형이 다르므로 변환과정에서 오차 생겨 불가능

epsilon 해결법

if (std::abs(a - b) <= absEpsilon)
        return true;
  • 따라서 두 소수의 차이가 Epsilon보다 작으면 같다고 판정
  • 그러나 1.01.00001이 다르다는 것은 괜찮지만, 100000.0100000.00001도 다르다고 하기에는 문제가 있어보임
bool approximatelyEqualAbsRel(double a, double b, double absEpsilon, double relEpsilon)
{
    // 먼저 epsilon으로 비교
    if (std::abs(a - b) <= absEpsilon)
        return true;

    // 상대적 epsilon으로 재비교
    return (std::abs(a - b) <= (std::max(std::abs(a), std::abs(b)) * relEpsilon));
}
  • 그래서 relEpsilon을 통해 비교하는 수의 크기에 따라 epsilon의 크기도 조정하여 판단한다

Reference

learn.cpp

profile
반갑습니다

0개의 댓글