728x90
반응형
- 실수(부동소수점) 계산은 계산 과정에서 아주 작은 오차가 누적되기 때문에,
==
같은 정확한 비교는 거의 항상 실패합니다. - 따라서
C++
테스트 코드에서는 일정 오차 허용 범위 내의 비교, 즉 근사 비교(Approximate Comparison) 가 필수입니다.
-
이를 지원하는 주요 프레임워크는 다음과 같습니다:
-
프레임워크 근사 비교 함수 오차 유형 공식 홈페이지 URL doctest doctest::Approx()
상대 오차 https://github.com/doctest/doctest Catch2 Catch::Approx()
상대/절대 오차 혼합 https://github.com/catchorg/Catch2 Google Test EXPECT_NEAR()
절대 오차 https://github.com/google/googletest Boost.Test BOOST_CHECK_CLOSE()
상대 오차 (%) https://www.boost.org/doc/libs/release/libs/test/ Eigen isApprox()
상대/절대 오차 https://eigen.tuxfamily.org/
- 각 프레임워크는 다른 방식으로 오차를 정의하고 비교하므로, 정확한 테스트를 위해 각 기능의 특징을 이해하고 사용하는 것이 중요합니다.
-
cpp
#include <doctest/doctest.h> TEST_CASE("예제") { double halfpi = 1.5707963; REQUIRE(halfpi == doctest::Approx(1.5707963)); }
epsilon()
으로 상대 오차 정밀도 조절 가능- 기본
epsilon = 1e-12
- 오차 계산:
-
cpp
std::fabs(lhs - rhs) <= epsilon × max(|lhs|, |rhs|)
-
-
비교값 통과 여부 (기본 설정 기준) 1.57079629
✅ 통과 1.57079631
✅ 통과 1.5707964
❌ 실패 가능성 높음
-
cpp
REQUIRE(1.57079631 == doctest::Approx(1.5707963).epsilon(1e-9)); // 허용 REQUIRE(1.57079631 == doctest::Approx(1.5707963).epsilon(1e-13)); // 실패 가능
-
cpp
#include <catch2/catch.hpp> TEST_CASE("Catch2 근사 비교") { double val = 1.5707963; REQUIRE(val == Catch::Approx(1.5707963)); }
- 사용법 및
API
는doctest
와 거의 동일 .epsilon()
,.margin()
으로 정밀도 조절 가능
-
cpp
#include <gtest/gtest.h> TEST(FloatingPointTest, NearTest) { double val = 1.5707963; EXPECT_NEAR(val, 1.5707963, 1e-9); // 절대 오차 }
- 세 번째 인자로 절대 오차를 지정 (
1e-9
) - 상대 오차는 직접 계산해야 함
-
cpp
#include <boost/test/unit_test.hpp> BOOST_AUTO_TEST_CASE(test_close) { double val = 1.5707963; BOOST_CHECK_CLOSE(val, 1.5707963, 0.0001); // 0.0001% 허용 오차 }
- 상대 오차를 퍼센트(
%
) 로 지정 - 오차 계산:
100 * |a - b| / max(|a|, |b|)
-
cpp
#include <Eigen/Dense> Eigen::VectorXd a(2), b(2); a << 1.0, 2.0; b << 1.0, 2.000000001; bool is_close = a.isApprox(b, 1e-9);
- 주로 벡터/행렬 비교에 사용
- 상대 오차 비교 (기본값 존재)
-
cpp
#include <cmath> double a = 1.5707963; double b = 1.57079631; double epsilon = 1e-9; if (std::fabs(a - b) < epsilon) { // 근사적으로 같다 }
- 가장 쉽게 구현하는 방식
- 테스트 프레임워크 메시지가 없어 불편함
-
프레임워크 함수 오차 방식 조절 방식 특징 doctest
doctest::Approx()
상대 오차 .epsilon()
,.scale()
직관적, Catch2
와 유사Catch2
Catch::Approx()
상대/절대 혼합 .epsilon()
,.margin()
직관적, doctest
와 유사Google Test
EXPECT_NEAR()
절대 오차 세 번째 인자로 오차 간단하지만 유연성 낮음 Boost.Test
BOOST_CHECK_CLOSE()
상대 오차 ( %
)퍼센트 지정 오래된 스타일의 매크로 Eigen
isApprox()
상대/절대 오차 두 번째 인자로 오차 벡터/행렬에 적합 C++
표준 방식std::fabs(a - b) < e
절대 오차 직접 구현 메시지 부족, 보조적 사용
doctest::Approx()
는 작고 빠르면서도 강력한 부동소수점 근사 비교 기능을 제공합니다.Catch2::Approx()
와 거의 동일한 인터페이스를 가지며, 상대 오차 기반으로 정밀도 제어가 가능합니다.
- 보다 복잡한 비교나 절대 오차 비교가 필요한 경우
Google Test
,Boost.Test
,Eigen
등 다른 프레임워크의 기능을 활용하면 됩니다. - 어떤 방식이든, 부동소수점은 == 비교가 아니라 근사 비교가 기본 이 되어야 합니다.
- 테스트 정확도를 높이고자 한다면, 오차 허용 기준을 명확하게 정의 하고 그에 맞는 도구를 선택하는 것이 중요합니다.
- 도움이 되셨으면 하단의 ❤️ 공감 버튼 부탁 드립니다. 감사합니다! 😄
728x90
반응형
'C C++' 카테고리의 다른 글
C++ 뷰(View) 타입과 소유(Ownership) 타입 (0) | 2025.03.29 |
---|---|
C++20 분기 예측 : [[likely]], [[unlikely]] (0) | 2025.03.29 |
C++11 =default 와 =delete (0) | 2025.03.28 |
C++ 예외 처리(exception) 비결정(non-deterministic) (0) | 2025.03.28 |
Modern C++ 순회 방법(Iteration)과 구조 분해(Structured Bindings) (0) | 2025.03.28 |