数值极限
std::numeric_limits
定义于头文件 <limits>
定义于头文件 | ||
template< class T > class numeric_limits; |
numeric_limits 类模板提供查询各种算术类型属性的标准化方式(例如 int 类型的最大可能值是 std::numeric_limits<int>::max() )。
鉴别可能导致算术运算出现陷阱的类型
std::numeric_limits<T>::traps
static const bool traps; | (C++11 前) | |
static constexpr bool traps; | (C++11 起) |
std::numeric_limits<T>::traps 的值,对所有至少有一个若用作算术运算参数则会生成陷阱的值的算术类型 T
为 true 。
标准特化
T | std::numeric_limits<T>::traps 的值 |
/* non-specialized */ | false |
bool | false |
char | 通常为 true |
signed char | 通常为 true |
unsigned char | 通常为 true |
wchar_t | 通常为 true |
char8_t | 通常为 true |
char16_t | 通常为 true |
char32_t | 通常为 true |
short | 通常为 true |
unsigned short | 通常为 true |
int | 通常为 true |
unsigned int | 通常为 true |
long | 通常为 true |
unsigned long | 通常为 true |
long long | 通常为 true |
unsigned long long | 通常为 true |
float | 通常为 false |
double | 通常为 false |
long double | 通常为 false |
注意
大多数平台上,除以零始终会产生陷阱,而对所有支持值 0 的整数类型, std::numeric_limits<T>::traps 为 true 。例外是类型 bool :即使除以 false 因为从 bool 整数提升到 int 而产生陷阱,这也是零值的 int 所产生的陷阱。零不是 bool 的值。
大多数平台上,浮点异常可以在运行时开关(例如 Linux 上的 feenableexcept() 或 Windows 上的 _controlfp ),该情况下 std::numeric_limits<T>::traps 对浮点类型的值反映程序启动时的浮点陷阱设施,它在大多数现代系统上为 false 。 DEC Alpha 程序可以是例外,若不以 -ieee
编译程序,则为 true 。
调用示例
#include <iostream>
#include <string>
#include <limits>
#include <cstdint>
#include <cfloat>
struct SName
{
};
//偏特化
struct SPartSpec
{
};
namespace std
{
template<>
struct numeric_limits<SPartSpec>
{
static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true;
static _GLIBCXX_USE_CONSTEXPR bool is_signed = true;
static _GLIBCXX_USE_CONSTEXPR bool is_integer = true;
static _GLIBCXX_USE_CONSTEXPR bool is_exact = true;
static _GLIBCXX_USE_CONSTEXPR bool has_infinity = true;
static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = true;
static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = true;
static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm = denorm_present;
static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = true;
static _GLIBCXX_USE_CONSTEXPR float_round_style round_style = round_toward_neg_infinity;
static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = true;
static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true;
static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true;
static _GLIBCXX_USE_CONSTEXPR int digits = CHAR_BIT;
static _GLIBCXX_USE_CONSTEXPR int digits10 = CHAR_BIT;
static _GLIBCXX_USE_CONSTEXPR int max_digits10 = DECIMAL_DIG;
static _GLIBCXX_USE_CONSTEXPR int radix = FLT_RADIX;
static _GLIBCXX_USE_CONSTEXPR int min_exponent = FLT_MIN_EXP;
static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = FLT_MIN_10_EXP;
static _GLIBCXX_USE_CONSTEXPR int max_exponent = FLT_MAX_EXP;
static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = FLT_MAX_EXP;
static _GLIBCXX_USE_CONSTEXPR bool traps = true;
};
}
int main()
{
std::cout << std::boolalpha;
std::cout << "std::numeric_limits<bool>::traps: "
<< std::numeric_limits<bool>::traps << std::endl;
std::cout << "std::numeric_limits<char>::traps: "
<< std::numeric_limits<char>::traps << std::endl;
std::cout << "std::numeric_limits<signed char>::traps: "
<< std::numeric_limits<signed char>::traps << std::endl;
std::cout << "std::numeric_limits<unsigned char>::traps: "
<< std::numeric_limits<unsigned char>::traps << std::endl;
std::cout << "std::numeric_limits<wchar_t>::traps: "
<< std::numeric_limits<wchar_t>::traps << std::endl;
std::cout << "std::numeric_limits<char16_t>::traps: "
<< std::numeric_limits<char16_t>::traps << std::endl;
std::cout << "std::numeric_limits<char32_t>::traps: "
<< std::numeric_limits<char32_t>::traps << std::endl;
std::cout << "std::numeric_limits<short>::traps: "
<< std::numeric_limits<short>::traps << std::endl;
std::cout << "std::numeric_limits<unsigned short>::traps: "
<< std::numeric_limits<unsigned short>::traps << std::endl;
std::cout << "std::numeric_limits<int>::traps: "
<< std::numeric_limits<int>::traps << std::endl;
std::cout << "std::numeric_limits<unsigned int>::traps: "
<< std::numeric_limits<unsigned int>::traps << std::endl;
std::cout << "std::numeric_limits<long>::traps: "
<< std::numeric_limits<long>::traps << std::endl;
std::cout << "std::numeric_limits<unsigned long>::traps: "
<< std::numeric_limits<unsigned long>::traps << std::endl;
std::cout << "std::numeric_limits<long long>::traps: "
<< std::numeric_limits<long long>::traps << std::endl;
std::cout << "std::numeric_limits<unsigned long long>::traps: "
<< std::numeric_limits<unsigned long long>::traps << std::endl;
std::cout << "std::numeric_limits<float>::traps: "
<< std::numeric_limits<float>::traps << std::endl;
std::cout << "std::numeric_limits<double>::traps: "
<< std::numeric_limits<double>::traps << std::endl;
std::cout << "std::numeric_limits<long double>::traps: "
<< std::numeric_limits<long double>::traps << std::endl;
std::cout << "std::numeric_limits<std::string>::traps: "
<< std::numeric_limits<std::string>::traps << std::endl;
std::cout << "std::numeric_limits<SName>::traps: "
<< std::numeric_limits<SName>::traps << std::endl;
std::cout << "std::numeric_limits<SPartSpec>::traps: "
<< std::numeric_limits<SPartSpec>::traps << std::endl;
return 0;
}
输出
鉴别检测舍入前是否非正规的浮点类型
std::numeric_limits<T>::tinyness_before
static const bool tinyness_before; | (C++11 前) | |
static constexpr bool tinyness_before; | (C++11 起) |
std::numeric_limits<T>::tinyness_before 的值对所有测试浮点表达式在舍入前下溢的浮点类型 T
为 true 。
标准特化
T | std::numeric_limits<T>::tinyness_before 的值 |
/* non-specialized */ | false |
bool | false |
char | false |
signed char | false |
unsigned char | false |
wchar_t | false |
char8_t | false |
char16_t | false |
char32_t | false |
short | false |
unsigned short | false |
int | false |
unsigned int | false |
long | false |
unsigned long | false |
long long | false |
unsigned long long | false |
float | 实现定义 |
double | 实现定义 |
long double | 实现定义 |
注意
符合标准的 IEEE 754 浮点实现要求检测浮点下溢,并在执行处有二种可选的情形
1) 若假如以指数范围和精度均为无界的计算,产生绝对值小于 std::numeric_limits<T>::min() 的结果,则发生下溢(并且可能引发 FE_UNDERFLOW )。这种实现在舍入前检测是否较小(如 UltraSparc 、 POWER )。
2) 若舍入到目标浮点类型(即舍入到 std::numeric_limits<T>::digits 位)后,结果的绝对值小于 std::numeric_limits<T>::min() ,则发生下溢(并且可能引发 FE_UNDERFLOW )。正式地说,假如以指数范围和精度均为无界的计算,非零结果的绝对值小于 std::numeric_limits<T>::min() 。这种实现在舍入后检测是否较小(如 SuperSparc )
调用示例
#include <iostream>
#include <string>
#include <limits>
#include <cstdint>
#include <cfloat>
struct SName
{
};
//偏特化
struct SPartSpec
{
};
namespace std
{
template<>
struct numeric_limits<SPartSpec>
{
static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true;
static _GLIBCXX_USE_CONSTEXPR bool is_signed = true;
static _GLIBCXX_USE_CONSTEXPR bool is_integer = true;
static _GLIBCXX_USE_CONSTEXPR bool is_exact = true;
static _GLIBCXX_USE_CONSTEXPR bool has_infinity = true;
static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = true;
static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = true;
static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm = denorm_present;
static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = true;
static _GLIBCXX_USE_CONSTEXPR float_round_style round_style = round_toward_neg_infinity;
static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = true;
static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true;
static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true;
static _GLIBCXX_USE_CONSTEXPR int digits = CHAR_BIT;
static _GLIBCXX_USE_CONSTEXPR int digits10 = CHAR_BIT;
static _GLIBCXX_USE_CONSTEXPR int max_digits10 = DECIMAL_DIG;
static _GLIBCXX_USE_CONSTEXPR int radix = FLT_RADIX;
static _GLIBCXX_USE_CONSTEXPR int min_exponent = FLT_MIN_EXP;
static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = FLT_MIN_10_EXP;
static _GLIBCXX_USE_CONSTEXPR int max_exponent = FLT_MAX_EXP;
static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = FLT_MAX_EXP;
static _GLIBCXX_USE_CONSTEXPR bool traps = true;
static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = true;
};
}
int main()
{
std::cout << std::boolalpha;
std::cout << "std::numeric_limits<bool>::tinyness_before: "
<< std::numeric_limits<bool>::tinyness_before << std::endl;
std::cout << "std::numeric_limits<char>::tinyness_before: "
<< std::numeric_limits<char>::tinyness_before << std::endl;
std::cout << "std::numeric_limits<signed char>::tinyness_before: "
<< std::numeric_limits<signed char>::tinyness_before << std::endl;
std::cout << "std::numeric_limits<unsigned char>::tinyness_before: "
<< std::numeric_limits<unsigned char>::tinyness_before << std::endl;
std::cout << "std::numeric_limits<wchar_t>::tinyness_before: "
<< std::numeric_limits<wchar_t>::tinyness_before << std::endl;
std::cout << "std::numeric_limits<char16_t>::tinyness_before: "
<< std::numeric_limits<char16_t>::tinyness_before << std::endl;
std::cout << "std::numeric_limits<char32_t>::tinyness_before: "
<< std::numeric_limits<char32_t>::tinyness_before << std::endl;
std::cout << "std::numeric_limits<short>::tinyness_before: "
<< std::numeric_limits<short>::tinyness_before << std::endl;
std::cout << "std::numeric_limits<unsigned short>::tinyness_before: "
<< std::numeric_limits<unsigned short>::tinyness_before << std::endl;
std::cout << "std::numeric_limits<int>::tinyness_before: "
<< std::numeric_limits<int>::tinyness_before << std::endl;
std::cout << "std::numeric_limits<unsigned int>::tinyness_before: "
<< std::numeric_limits<unsigned int>::tinyness_before << std::endl;
std::cout << "std::numeric_limits<long>::tinyness_before: "
<< std::numeric_limits<long>::tinyness_before << std::endl;
std::cout << "std::numeric_limits<unsigned long>::tinyness_before: "
<< std::numeric_limits<unsigned long>::tinyness_before << std::endl;
std::cout << "std::numeric_limits<long long>::tinyness_before: "
<< std::numeric_limits<long long>::tinyness_before << std::endl;
std::cout << "std::numeric_limits<unsigned long long>::tinyness_before: "
<< std::numeric_limits<unsigned long long>::tinyness_before << std::endl;
std::cout << "std::numeric_limits<float>::tinyness_before: "
<< std::numeric_limits<float>::tinyness_before << std::endl;
std::cout << "std::numeric_limits<double>::tinyness_before: "
<< std::numeric_limits<double>::tinyness_before << std::endl;
std::cout << "std::numeric_limits<long double>::tinyness_before: "
<< std::numeric_limits<long double>::tinyness_before << std::endl;
std::cout << "std::numeric_limits<std::string>::tinyness_before: "
<< std::numeric_limits<std::string>::tinyness_before << std::endl;
std::cout << "std::numeric_limits<SName>::tinyness_before: "
<< std::numeric_limits<SName>::tinyness_before << std::endl;
std::cout << "std::numeric_limits<SPartSpec>::tinyness_before: "
<< std::numeric_limits<SPartSpec>::tinyness_before << std::endl;
return 0;
}