定义于头文件
| 定义于头文件 | ||
| template< class T > class numeric_limits; |
numeric_limits 类模板提供查询各种算术类型属性的标准化方式(例如 int 类型的最大可能值是 std::numeric_limits
std::numeric_limits<T>::is_modulo
| static const bool is_modulo; | (C++11 前) | |
| static constexpr bool is_modulo; | (C++11 起) |
std::numeric_limitsT 为 true 。模算术即若此类型的加法、减法、乘法或除法结果会落在范围 [min(), max()] 外,则这种运算返回的结果与期望值相差 max()-min()+1 的整数倍。
|
| (C++11 起) |
T | std::numeric_limits |
| /* non-specialized */ | false |
| bool | false |
| char | 实现定义 |
| signed char | 实现定义 |
| unsigned char | true |
| wchar_t | 实现定义 |
| char8_t | true |
| char16_t | true |
| char32_t | true |
| short | 实现定义 |
| unsigned short | true |
| int | 实现定义 |
| unsigned int | true |
| long | 实现定义 |
| unsigned long | true |
| long long | 实现定义 |
| unsigned long long | true |
| float | false |
| double | false |
| long double | false |
尽管 C++11 标准仍然说“在大多数机器上,这对于有符号整数为 true ”,这是缺陷而且已被更正。准确措辞从 C++03 到 C++11 的更改使得 true 值不再与有符号整数溢出上的未定义行为兼容。因此,依赖于有符号溢出为未定义(为了优化机会)的实现现在对有符号整数设置 is_modulo 为 false 。见示例 GCC PR 22200 。
- #include <iostream>
- #include <string>
- #include <limits>
-
- 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;
- };
- }
-
- int main()
- {
- std::cout << std::boolalpha;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<bool>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<char>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<signed char>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<unsigned char>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<wchar_t>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<char16_t>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<char32_t>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<short>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<unsigned short>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<int>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<unsigned int>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<long>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<unsigned long>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<long long>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<unsigned long long>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<float>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<double>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<long double>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<std::string>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<SName>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<SPartSpec>::is_modulo << std::endl;
- return 0;
- }

std::numeric_limits<T>::digits
| static const int digits; | (C++11 前) | |
| static constexpr int digits; | (C++11 起) |
std::numeric_limitsT 的 radix 底位数。对于整数类型,这是不含符号位和填充位(若存在)的位数。对于浮点类型,这是尾数的位数。
T | std::numeric_limits |
| /* non-specialized */ | 0 |
| bool | 1 |
| char | CHAR_BIT - std::numeric_limits |
| signed char | CHAR_BIT - 1 |
| unsigned char | CHAR_BIT |
| wchar_t | CHAR_BIT*sizeof(wchar_t) - std::numeric_limits |
| char8_t | CHAR_BIT |
| char16_t | CHAR_BIT*sizeof(char16_t) |
| char32_t | CHAR_BIT*sizeof(char32_t) |
| short | CHAR_BIT*sizeof(short)-1 |
| unsigned short | CHAR_BIT*sizeof(short) |
| int | CHAR_BIT*sizeof(int)-1 |
| unsigned int | CHAR_BIT*sizeof(int) |
| long | CHAR_BIT*sizeof(long)-1 |
| unsigned long | CHAR_BIT*sizeof(long) |
| long long | CHAR_BIT*sizeof(long long)-1 |
| unsigned long long | CHAR_BIT*sizeof(long long) |
| float | FLT_MANT_DIG |
| double | DBL_MANT_DIG |
| long double | LDBL_MANT_DIG |
- #include <iostream>
- #include <string>
- #include <limits>
- #include <cstdint>
-
- 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;
- };
- }
-
- int main()
- {
- std::cout << std::boolalpha;
- std::cout << "std::numeric_limits
::digits: " - << std::numeric_limits<bool>::digits << std::endl;
- std::cout << "std::numeric_limits
::digits: " - << std::numeric_limits<char>::digits << std::endl;
- std::cout << "std::numeric_limits
::digits: " - << std::numeric_limits<signed char>::digits << std::endl;
- std::cout << "std::numeric_limits
::digits: " - << std::numeric_limits<unsigned char>::digits << std::endl;
- std::cout << "std::numeric_limits
::digits: " - << std::numeric_limits<wchar_t>::digits << std::endl;
- std::cout << "std::numeric_limits
::digits: " - << std::numeric_limits<char16_t>::digits << std::endl;
- std::cout << "std::numeric_limits
::digits: " - << std::numeric_limits<char32_t>::digits << std::endl;
- std::cout << "std::numeric_limits
::digits: " - << std::numeric_limits<short>::digits << std::endl;
- std::cout << "std::numeric_limits
::digits: " - << std::numeric_limits<unsigned short>::digits << std::endl;
- std::cout << "std::numeric_limits
::digits: " - << std::numeric_limits<int>::digits << std::endl;
- std::cout << "std::numeric_limits
::digits: " - << std::numeric_limits<unsigned int>::digits << std::endl;
- std::cout << "std::numeric_limits
::digits: " - << std::numeric_limits<long>::digits << std::endl;
- std::cout << "std::numeric_limits
::digits: " - << std::numeric_limits<unsigned long>::digits << std::endl;
- std::cout << "std::numeric_limits
::digits: " - << std::numeric_limits<long long>::digits << std::endl;
- std::cout << "std::numeric_limits
::digits: " - << std::numeric_limits<unsigned long long>::digits << std::endl;
- std::cout << "std::numeric_limits
::digits: " - << std::numeric_limits<float>::digits << std::endl;
- std::cout << "std::numeric_limits
::digits: " - << std::numeric_limits<double>::digits << std::endl;
- std::cout << "std::numeric_limits
::digits: " - << std::numeric_limits<long double>::digits << std::endl;
- std::cout << "std::numeric_limits
::digits: " - << std::numeric_limits<std::string>::digits << std::endl;
- std::cout << "std::numeric_limits
::digits: " - << std::numeric_limits<SName>::digits << std::endl;
- std::cout << "std::numeric_limits
::digits: " - << std::numeric_limits<SPartSpec>::digits << std::endl;
- return 0;
- }
-
- int is_modulo()
- {
- std::cout << std::boolalpha;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<bool>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<char>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<signed char>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<unsigned char>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<wchar_t>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<char16_t>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<char32_t>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<short>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<unsigned short>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<int>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<unsigned int>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<long>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<unsigned long>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<long long>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<unsigned long long>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<float>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<double>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<long double>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<std::string>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<SName>::is_modulo << std::endl;
- std::cout << "std::numeric_limits
::is_modulo: " - << std::numeric_limits<SPartSpec>::is_modulo << std::endl;
- return 0;
- }

std::numeric_limits<T>::digits10
| static const int digits10; | (C++11 前) | |
| static constexpr int digits10 | (C++11 起) |
std::numeric_limitsT 能无更改地表示的底 10 位数,即任何拥有这么多十进制有效数字的数能转换成 T 的值并转换回十进制形式,而不因舍入或上溢而更改。对于底 radix 类型,它是 digits (对于浮点类型是 digits-1 )的值乘 log
10(radix) 并向下取整。
T | std::numeric_limits |
| /* non-specialized */ | 0 |
| bool | 0 |
| char | std::numeric_limits |
| signed char | std::numeric_limits |
| unsigned char | std::numeric_limits |
| wchar_t | std::numeric_limits |
| char8_t | std::numeric_limits |
| char16_t | std::numeric_limits |
| char32_t | std::numeric_limits |
| short | std::numeric_limits |
| unsigned short | std::numeric_limits |
| int | std::numeric_limits |
| unsigned int | std::numeric_limits |
| long | std::numeric_limits |
| unsigned long | std::numeric_limits |
| long long | std::numeric_limits |
| unsigned long long | std::numeric_limits |
| float | FLT_DIG /* IEEE float 为 6 */ |
| double | DBL_DIG /* IEEE double 为 15 */ |
| long double | LDBL_DIG /* 80 位 Intel long double 为 18 */ |
8 位二进制类型能准确表示任何二位十进制数,但不能表示 3 位十进制数 256..999 。 digits10 对 8 位类型的值是 2 ( 8 * std::log10(2) 为 2.41 )
标准 32 位 IEEE 754 浮点类型拥有 24 位小数部分(写出 23 位,隐含一位),这可以建议它能表示 7 位十进制数字( 24 * std::log10(2) 为 7.22 ),但相对误差不统一,且一些有 7 位十进制数的浮点值不能在转换到 32 位浮点再转换回来后生存:最小的正数例子是 8.589973e9 ,它在来回舍入后变成 8.589974e9 。这些误差在表示中不能超过一位,而 digits10 按 (24-1)*std::log10(2) 计算,即 6.92 。向下取整结果导致值 6 。
类似地,16 字符串 9007199254740993 在文本->double->文本回环中不保持,它变为 9007199254740992 : 64 位 IEEE 754 double 类型仅保证 15 位的舍入回环。
- #include <iostream>
- #include <string>
- #include <limits>
- #include <cstdint>
-
- 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;
- };
- }
-
- int main()
- {
- std::cout << std::boolalpha;
- std::cout << "std::numeric_limits
::digits10: " - << std::numeric_limits<bool>::digits10 << std::endl;
- std::cout << "std::numeric_limits
::digits10: " - << std::numeric_limits<char>::digits10 << std::endl;
- std::cout << "std::numeric_limits
::digits10: " - << std::numeric_limits<signed char>::digits10 << std::endl;
- std::cout << "std::numeric_limits
::digits10: " - << std::numeric_limits<unsigned char>::digits10 << std::endl;
- std::cout << "std::numeric_limits
::digits10: " - << std::numeric_limits<wchar_t>::digits10 << std::endl;
- std::cout << "std::numeric_limits
::digits10: " - << std::numeric_limits<char16_t>::digits10 << std::endl;
- std::cout << "std::numeric_limits
::digits10: " - << std::numeric_limits<char32_t>::digits10 << std::endl;
- std::cout << "std::numeric_limits
::digits10: " - << std::numeric_limits<short>::digits10 << std::endl;
- std::cout << "std::numeric_limits
::digits10: " - << std::numeric_limits<unsigned short>::digits10 << std::endl;
- std::cout << "std::numeric_limits
::digits10: " - << std::numeric_limits<int>::digits10 << std::endl;
- std::cout << "std::numeric_limits
::digits10: " - << std::numeric_limits<unsigned int>::digits10 << std::endl;
- std::cout << "std::numeric_limits
::digits10: " - << std::numeric_limits<long>::digits10 << std::endl;
- std::cout << "std::numeric_limits
::digits10: " - << std::numeric_limits<unsigned long>::digits10 << std::endl;
- std::cout << "std::numeric_limits
::digits10: " - << std::numeric_limits<long long>::digits10 << std::endl;
- std::cout << "std::numeric_limits
::digits10: " - << std::numeric_limits<unsigned long long>::digits10 << std::endl;
- std::cout << "std::numeric_limits
::digits10: " - << std::numeric_limits<float>::digits10 << std::endl;
- std::cout << "std::numeric_limits
::digits10: " - << std::numeric_limits<double>::digits10 << std::endl;
- std::cout << "std::numeric_limits
::digits10: " - << std::numeric_limits<long double>::digits10 << std::endl;
- std::cout << "std::numeric_limits
::digits10: " - << std::numeric_limits<std::string>::digits10 << std::endl;
- std::cout << "std::numeric_limits
::digits10: " - << std::numeric_limits<SName>::digits10 << std::endl;
- std::cout << "std::numeric_limits
::digits10: " - << std::numeric_limits<SPartSpec>::digits10 << std::endl;
- return 0;
- }
