수치 한계와 특성 (Numeric Limits with std::numeric_limits)
개요
std::numeric_limits
는 C++ 표준 라이브러리의 <limits>
헤더에 정의된 템플릿 클래스로, 기본 숫자 타입들의 속성과 한계를 조회하는 데 사용됩니다. 이 클래스를 통해 타입의 최대값, 최소값, 정밀도 등 다양한 수치적 특성을 컴파일 타임에 얻을 수 있습니다.
C++ 버전별 주요 키워드 도입 시기
- C++98: 기본
std::numeric_limits
템플릿 클래스 도입 - C++11:
lowest()
,max_digits10
등 추가 멤버 함수 도입 - C++17:
is_iec559
를 통한 IEEE 754 부동소수점 준수 여부 확인
내용 설명
1. 기본 사용법
std::numeric_limits
는 템플릿 클래스로, 특정 타입에 대한 수치적 특성을 조회할 수 있습니다. 정수형과 부동소수점 타입 모두에 대해 특화되어 있습니다.
2. 주요 멤버 상수 및 함수
min()
: 타입이 표현할 수 있는 최소 유한값max()
: 타입이 표현할 수 있는 최대 유한값lowest()
: 타입이 표현할 수 있는 가장 작은 값 (부동소수점의 경우 -max()와 동일)epsilon()
: 1과 1+epsilon이 구분될 수 있는 가장 작은 값 (부동소수점 전용)digits
: 가수부 비트 수 (부동소수점) 또는 비트 폭 (정수형)digits10
: 10진수로 표현 가능한 자릿수is_signed
: 부호 있는 타입인지 여부is_integer
: 정수형인지 여부is_exact
: 정확한 표현이 가능한지 여부has_infinity
: 무한대를 표현할 수 있는지 여부
3. 부동소수점 비교
부동소수점 숫자는 이진 표현의 한계로 인해 정확한 비교가 어려울 수 있습니다. epsilon()
을 사용하여 두 부동소수점이 근사적으로 같은지 비교할 수 있습니다.
예제 코드
#include <cmath>
#include <cstdint>
#include <iostream>
#include <limits>
template <typename T>
void print_type_properties()
{
std::cout << "min=" << std::numeric_limits<T>::min() << '\n'
<< "max=" << std::numeric_limits<T>::max() << '\n'
<< "bits=" << std::numeric_limits<T>::digits << '\n'
<< "decdigits=" << std::numeric_limits<T>::digits10 << '\n'
<< "integral=" << std::boolalpha
<< std::numeric_limits<T>::is_integer << '\n'
<< "signed=" << std::boolalpha
<< std::numeric_limits<T>::is_signed << '\n'
<< "exact=" << std::boolalpha << std::numeric_limits<T>::is_exact
<< '\n'
<< "infinity=" << std::boolalpha
<< std::numeric_limits<T>::has_infinity << '\n'
<< '\n';
}
template <typename T>
bool equal(const T x, const T y)
{
return x == y;
}
template <typename T>
bool almost_equal(const T x, const T y)
{
return std::abs(x - y) <= std::numeric_limits<T>::epsilon();
}
int main()
{
std::cout << "=== std::uint16_t ===\n";
print_type_properties<std::uint16_t>();
std::cout << "=== std::int32_t ===\n";
print_type_properties<std::int32_t>();
std::cout << "=== float ===\n";
print_type_properties<float>();
const auto d1 = 0.2;
const auto d2 = 1.0 / (std::sqrt(5.0) * std::sqrt(5.0)); // == 1 / 5
std::cout << "d1 = " << d1 << '\n';
std::cout << "d2 = " << d2 << '\n';
std::cout.precision(17);
std::cout << "d1 (high precision) = " << d1 << '\n';
std::cout << "d2 (high precision) = " << d2 << '\n';
std::cout << "d1 == d2? " << std::boolalpha << equal(d1, d2) << '\n';
std::cout << "epsilon = " << std::numeric_limits<float>::epsilon() << '\n';
std::cout << "d1 ~= d2? " << std::boolalpha << almost_equal(d1, d2) << '\n';
return 0;
}
실행 결과
=== std::uint16_t ===
min=0
max=65535
bits=16
decdigits=4
integral=true
signed=false
exact=true
infinity=false
=== std::int32_t ===
min=-2147483648
max=2147483647
bits=31
decdigits=9
integral=true
signed=true
exact=true
infinity=false
=== float ===
min=1.17549e-38
max=3.40282e+38
bits=24
decdigits=6
integral=false
signed=true
exact=false
infinity=true
d1 = 0.2
d2 = 0.2
d1 (high precision) = 0.20000000000000001
d2 (high precision) = 0.20000000000000004
d1 == d2? false
epsilon = 1.19209e-07
d1 ~= d2? true
활용팁
- 타입 독립적인 코드 작성 시:
std::numeric_limits
를 사용하면 템플릿 코드에서 타입에 따라 다른 동작을 구현할 수 있습니다. - 안전한 수치 연산: 오버플로우나 언더플로우를 방지하기 위해 연산 전에
min()
과max()
를 확인하세요. - 부동소수점 비교:
==
연산자 대신std::abs(a - b) < epsilon
패턴을 사용하여 부동소수점을 비교하세요. - 플랫폼 독립성:
int
나long
같은 타입의 크기는 플랫폼에 따라 다를 수 있으므로, 특정 크기가 필요한 경우int32_t
같은 고정 크기 정수형을 사용하세요. - 컴파일 타임 상수:
std::numeric_limits
의 멤버들은 컴파일 타임 상수이므로,static_assert
와 함께 사용하여 타입 요구사항을 검증할 수 있습니다.
'개발 > C++ (98,03,11,14,17,20,23)' 카테고리의 다른 글
Modern C++ : std::chrono 날짜 및 시간대 (11, 14, 17, 20) (1) | 2025.09.06 |
---|---|
Modern C++ : std::chrono 시간 측정 (11, 14, 17, 20) (0) | 2025.09.05 |
Modern C++ : std::mt19937 (11, 14, 17, 20) (0) | 2025.09.04 |
Modern C++ : std::filesystem (0) | 2025.09.03 |
Modern C++ : std::ostream & std::istream (98, 11, 17, 20) (0) | 2025.09.02 |
Modern C++ : std::string_view (17, 20) (1) | 2025.09.01 |
Modern C++ : Small String Optimization (SSO) (3) | 2025.08.31 |
Modern C++ : std::string (98, 11, 17, 20) (3) | 2025.08.30 |