Skip to content
SEUNGLAB.dev
GithubLinkedIn

C++의 numeric_limits

Code5 min read

C++을 사용하다 보면 숫자 타입들의 최댓값과 최솟값을 활용해야 하는 경우가 있다. 이런 경우에 우리는 numeric_limits<int>::min, numeric_limits<float>::max 와 같이 산술 타입의 다양한 속성을 표준화된 방법으로 조회할 수 있는 numeric_limits 클래스를 활용한다.

Sample Code

#include <limits>
#include <iostream>
int main()
{
std::cout
<< "type\t│ lowest()\t│ min()\t\t│ max()\n"
<< "bool\t│ "
<< std::numeric_limits<bool>::lowest() << "\t\t│ "
<< std::numeric_limits<bool>::min() << "\t\t│ "
<< std::numeric_limits<bool>::max() << '\n'
<< "uchar\t│ "
<< +std::numeric_limits<unsigned char>::lowest() << "\t\t│ "
<< +std::numeric_limits<unsigned char>::min() << "\t\t│ "
<< +std::numeric_limits<unsigned char>::max() << '\n'
<< "int\t│ "
<< std::numeric_limits<int>::lowest() << "\t│ "
<< std::numeric_limits<int>::min() << "\t│ "
<< std::numeric_limits<int>::max() << '\n'
<< "float\t│ "
<< std::numeric_limits<float>::lowest() << "\t│ "
<< std::numeric_limits<float>::min() << "\t│ "
<< std::numeric_limits<float>::max() << '\n'
<< "double\t│ "
<< std::numeric_limits<double>::lowest() << "\t│ "
<< std::numeric_limits<double>::min() << "\t│ "
<< std::numeric_limits<double>::max() << '\n';
}

Possible Output

type │ lowest() │ min() │ max()
bool │ 001
uchar │ 00255
int │ -2147483648 │ -2147483648 │ 2147483647
float │ -3.40282e+38 │ 1.17549e-38 │ 3.40282e+38
double │ -1.79769e+308 │ 2.22507e-308 │ 1.79769e+308

여기서 흥미로운 점이 하나 있다. 바로 가장 작은 값을 조회하는 방법이 min()lowest() 2가지라는 것이다. 심지어 floatdouble의 경우에는 2개의 값이 달랐다. 왜 이러한 차이가 발생한 것이며, 둘의 차이는 무엇일까?

numeric_limits<T>::min()

Returns the minimum finite value representable by the numeric type T. For floating-point types with denormalization, min returns the minimum positive normalized value. To find the value that has no values less than it, use numeric_limits::lowest.

숫자 형식 T로 나타낼 수 있는 최소 유한 값을 반환합니다. Denormalization이 있는 부동 소수점 유형의 경우 min은 정규화된 최소 양의 값을 반환합니다. 이 값보다 작은 값이 없는 값을 찾으려면 numeric_limits::lowest를 사용합니다.

해석을 해보기 앞서, Denormalization이란 무엇일까? IEEE-754 부동소수점 표현법에서 일반적으로 표현할 수 있는 수보다 더 작지만 0이 아닌 값을 말한다. 0과 부동소수점이 표현할 수 있는 최솟값의 사이에 존재하는 값이라고 생각하면 된다.

따라서 T에 Denormalization이 존재하는 부동소수점 타입이 들어왔을 때 min()은 부동소수점 표현법에서 일반적으로 표현 가능한 수들 중에서 0이 아닌 가장 작은 값을 반환한다.

만약 부동소수점 표현법과 관계없이 0이 아닌 이 값보다 더 작은 값이 없는, 말 그대로 진짜 최솟값을 찾고 싶은 경우 lowest()를 사용해야 한다.

numeric_limits<T>::lowest()

Returns the lowest finite value representable by the numeric type T, that is, a finite value x such that there is no other finite value y where y < x.

숫자 유형 T로 나타낼 수 있는 가장 낮은 유한 값, 즉 y < x에 다른 유한 값 y가 없는 유한 값 x를 반환합니다.

말 그대로 해당 값보다 더 작은 다른 유한값이 없는 값을 반환한다. 앞서 설명한 min()과는 달리 부동소수점의 표현법에 관여를 받지 않고 정말 가장 작은 값을 반환한다. 따라서 T에 Denormalization이 존재하는 부동소수점 타입이 들어오면, Denormalization값을 포함한 모든 값 중에서 가장 작은 값을 반환하는 것이다.

결론

부동소수점 타입에서 우리가 원하는 "진짜" 최솟값을 찾고 싶다면 반드시 lowest()를 사용하는 것이 좋다. 이는 부동소수점의 표현법과 상관없이, Denormalization값을 포함한 모든 값 중에서 가장 작은 값을 반환할 것이다.

One More Thing.

코드를 작성하면서 템플릿을 사용할 때가 있다. Ex) numeric_limits<T>::lowest()

이때 T에 정수타입이 입력될지 부동소수점 타입이 입력될지 알지 못함으로, 최솟값을 반환하는 기능을 원할 경우 항상 lowest()를 사용하는 것이 좋다.


References

std::numeric_limits

Denormalized number

Arithmetic underflow

IEEE 754