作用
cpp reference中介绍
std::numeric_limits是C++标准库中的一个模板类,它提供了关于基本数据类型的特性和限制的信息。
直白点说就是他提供了获取基本数据类型的相关信息的方法,让使用者不用去考虑操作系统和编译器的影响
举一个例子:
在32位程序中,int的最大值和64位程序中int的最大值是不一样的,当我们需要初始化某一个变量成int最大值的时候,需要考虑是32还是64位程序,但是如果直接使用std::numeric_limits获取int的最大值,则不用去考虑是32还是64位的程序了,这样代码也就更加简洁高效
标准库声明
namespace std { template<typename T> class numeric_limits { public: static constexpr bool is_specialized = false; static constexpr T min() noexcept { return T(); } static constexpr T max() noexcept { return T(); } static constexpr T lowest() noexcept { return T(); } static constexpr int digits = 0; static constexpr int digits10 = 0; static constexpr bool is_signed = false; static constexpr bool is_integer = false; static constexpr bool is_exact = false; static constexpr int radix = 0; static constexpr T epsilon() noexcept { return T(); } static constexpr T round_error() noexcept { return T(); } static constexpr int min_exponent = 0; static constexpr int min_exponent10 = 0; static constexpr int max_exponent = 0; static constexpr int max_exponent10 = 0; static constexpr bool has_infinity = false; static constexpr bool has_quiet_NaN = false; static constexpr bool has_signaling_NaN = false; static constexpr float_denorm_style has_denorm = denorm_absent; static constexpr bool has_denorm_loss = false; static constexpr T infinity() noexcept { return T(); } static constexpr T quiet_NaN() noexcept { return T(); } static constexpr T signaling_NaN() noexcept { return T(); } static constexpr T denorm_min() noexcept { return T(); } static constexpr bool is_iec559 = false; static constexpr bool is_bounded = false; static constexpr bool is_modulo = false; static constexpr bool traps = false; static constexpr bool tinyness_before = false; static constexpr float_round_style round_style = round_toward_zero; }; }
std::numeric_limits是一个模板类,使用时需要指定具体的数据类型T。该类中的所有成员函数和成员变量都是静态的,可以通过std::numeric_limits<T>::member_name的方式访问。
下面是std::numeric_limits的一些常用成员:
- is_specialized:一个布尔值,表示numeric_limits<T>是否已经为类型T进行了特化。
- min():返回类型T的最小值。
- max():返回类型T的最大值。
- lowest():返回类型T的最小有限值。
- digits:类型T的精确位数(二进制位数)。
- digits10:类型T的精确位数(十进制位数)。
- is_signed:一个布尔值,表示类型T是否是有符号类型。
- is_integer:一个布尔值,表示类型T是否是整数类型。
- is_exact:一个布尔值,表示类型T是否是精确类型。
- radix:表示类型T的基数。
- epsilon():类型T的最小可表示的绝对值。
- round_error():类型T的最小可表示的相对值。
- min_exponent:类型T的最小指数。
- min_exponent10`:类型T的最小十进制指数。
- max_exponent:类型T的最大指数。
- max_exponent10:类型T的最大十进制指数。
- has_infinity:一个布尔值,表示类型T是否有无穷大值。
- has_quiet_NaN:一个布尔值,表示类型T是否有静默NaN(Not-a-Number)值。
- has_signaling_NaN:一个布尔值,表示类型T是否有信号NaN(Not-a-Number)值。
- has_denorm:表示类型`T`的非规格化值的处理方式。
- has_denorm_loss:一个布尔值,表示类型T是否有非规格化值损失。
- infinity():返回类型T的无穷大值。
- quiet_NaN():返回类型T的静默NaN值。
- signaling_NaN():返回一个表示"signaling NaN"(信号非数)的特殊值
具体实现
std::numeric_limits 的具体实现是在编译器内实现的,这样就可以考虑到不同操作系统对标准库的影响。
例如VS2017的C++标准库中就是这么实现
namespace std { template<typename T> class numeric_limits { public: static constexpr bool is_specialized = true; static constexpr T min() noexcept { return _Min_value(static_cast<T*>(nullptr)); } static constexpr T max() noexcept { return _Max_value(static_cast<T*>(nullptr)); } static constexpr T lowest() noexcept { return (is_signed ? min() : T()); } static constexpr int digits = _Digits(static_cast<T*>(nullptr)); static constexpr int digits10 = _Digits10(static_cast<T*>(nullptr)); static constexpr bool is_signed = _Signed(static_cast<T*>(nullptr)); static constexpr bool is_integer = _Integer(static_cast<T*>(nullptr)); static constexpr bool is_exact = _Is_exact(static_cast<T*>(nullptr)); static constexpr int radix = _Radix(static_cast<T*>(nullptr)); static constexpr T epsilon() noexcept { return _Epsilon(static_cast<T*>(nullptr)); } static constexpr T round_error() noexcept { return _Round_error(static_cast<T*>(nullptr)); } static constexpr int min_exponent = _Min_exponent(static_cast<T*>(nullptr)); static constexpr int min_exponent10 = _Min_exponent10(static_cast<T*>(nullptr)); static constexpr int max_exponent = _Max_exponent(static_cast<T*>(nullptr)); static constexpr int max_exponent10 = _Max_exponent10(static_cast<T*>(nullptr)); static constexpr bool has_infinity = _Has_infinity(static_cast<T*>(nullptr)); static constexpr bool has_quiet_NaN = _Has_quiet_NaN(static_cast<T*>(nullptr)); static constexpr bool has_signaling_NaN = _Has_signaling_NaN(static_cast<T*>(nullptr)); static constexpr float_denorm_style has_denorm = _Has_denorm(static_cast<T*>(nullptr)); static constexpr bool has_denorm_loss = _Has_denorm_loss(static_cast<T*>(nullptr)); static constexpr T infinity() noexcept { return _Infinity(static_cast<T*>(nullptr)); } static constexpr T quiet_NaN() noexcept { return _Quiet_NaN(static_cast<T*>(nullptr)); } static constexpr T signaling_NaN() noexcept { return _Signaling_NaN(static_cast<T*>(nullptr)); } static constexpr T denorm_min() noexcept { return _Denorm_min(static_cast<T*>(nullptr)); } static constexpr bool is_iec559 = _Is_iec559(static_cast<T*>(nullptr)); static constexpr bool is_bounded = _Is_bounded(static_cast<T*>(nullptr)); static constexpr bool is_modulo = _Is_modulo(static_cast<T*>(nullptr)); static constexpr bool traps = _Traps(static_cast<T*>(nullptr)); static constexpr bool tinyness_before = _Tinyness_before(static_cast<T*>(nullptr)); static constexpr float_round_style round_style = _Round_style(static_cast<T*>(nullptr)); }; }
使用案例
下面给出一个简单的使用案例
#include <iostream> #include <limits> int main() { std::cout << "Minimum value for int: " << std::numeric_limits<int>::min() << std::endl; std::cout << "Maximum value for int: " << std::numeric_limits<int>::max() << std::endl; std::cout << "Number of digits for int: " << std::numeric_limits<int>::digits << std::endl; std::cout << "Number of decimal digits for int: " << std::numeric_limits<int>::digits10 << std::endl; std::cout << "Is int signed? " << std::numeric_limits<int>::is_signed << std::endl; std::cout << "Is int an integer type? " << std::numeric_limits<int>::is_integer << std::endl; std::cout << "Is int exact? " << std::numeric_limits<int>::is_exact << std::endl; return 0; }
可以看到只需要包含<limits>头文件,使用std::numeric_limits模板就可以简单获取基础类型的信息啦