• C++标准模板(STL)- 类型支持 (数值极限,is_modulo,digits,digits10)


    数值极限

    定义于头文件

    定义于头文件

    template< class T > class numeric_limits;

    numeric_limits 类模板提供查询各种算术类型属性的标准化方式(例如 int 类型的最大可能值是 std::numeric_limits::max() )。
     

    鉴别以模算术处理溢出的类型

    std::numeric_limits<T>::is_modulo

    static const bool is_modulo;

    (C++11 前)

    static constexpr bool is_modulo;

    (C++11 起)

    std::numeric_limits::is_modulo 对所有可能 (C++11 前)以模算术处理溢出的算术类型 T 为 true 。模算术即若此类型的加法、减法、乘法或除法结果会落在范围 [min(), max()] 外,则这种运算返回的结果与期望值相差 max()-min()+1 的整数倍。

    is_modulo有符号整数类型为 false ,除非实现定义有符号整数溢出为回绕。

    (C++11 起)

    标准特化

    Tstd::numeric_limits::is_modulo 的值
    /* non-specialized */false
    boolfalse
    char实现定义
    signed char实现定义
    unsigned chartrue
    wchar_t实现定义
    char8_ttrue
    char16_ttrue
    char32_ttrue
    short实现定义
    unsigned shorttrue
    int实现定义
    unsigned inttrue
    long实现定义
    unsigned longtrue
    long long实现定义
    unsigned long longtrue
    floatfalse
    doublefalse
    long doublefalse

    注意

    尽管 C++11 标准仍然说“在大多数机器上,这对于有符号整数为 true ”,这是缺陷而且已被更正。准确措辞从 C++03 到 C++11 的更改使得 true 值不再与有符号整数溢出上的未定义行为兼容。因此,依赖于有符号溢出为未定义(为了优化机会)的实现现在对有符号整数设置 is_modulofalse 。见示例 GCC PR 22200

    调用示例

    1. #include <iostream>
    2. #include <string>
    3. #include <limits>
    4. struct SName
    5. {
    6. };
    7. //偏特化
    8. struct SPartSpec
    9. {
    10. };
    11. namespace std
    12. {
    13. template<>
    14. struct numeric_limits<SPartSpec>
    15. {
    16. static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true;
    17. static _GLIBCXX_USE_CONSTEXPR bool is_signed = true;
    18. static _GLIBCXX_USE_CONSTEXPR bool is_integer = true;
    19. static _GLIBCXX_USE_CONSTEXPR bool is_exact = true;
    20. static _GLIBCXX_USE_CONSTEXPR bool has_infinity = true;
    21. static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = true;
    22. static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = true;
    23. static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm = denorm_present;
    24. static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = true;
    25. static _GLIBCXX_USE_CONSTEXPR float_round_style round_style = round_toward_neg_infinity;
    26. static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = true;
    27. static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true;
    28. static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true;
    29. };
    30. }
    31. int main()
    32. {
    33. std::cout << std::boolalpha;
    34. std::cout << "std::numeric_limits::is_modulo: "
    35. << std::numeric_limits<bool>::is_modulo << std::endl;
    36. std::cout << "std::numeric_limits::is_modulo: "
    37. << std::numeric_limits<char>::is_modulo << std::endl;
    38. std::cout << "std::numeric_limits::is_modulo: "
    39. << std::numeric_limits<signed char>::is_modulo << std::endl;
    40. std::cout << "std::numeric_limits::is_modulo: "
    41. << std::numeric_limits<unsigned char>::is_modulo << std::endl;
    42. std::cout << "std::numeric_limits::is_modulo: "
    43. << std::numeric_limits<wchar_t>::is_modulo << std::endl;
    44. std::cout << "std::numeric_limits::is_modulo: "
    45. << std::numeric_limits<char16_t>::is_modulo << std::endl;
    46. std::cout << "std::numeric_limits::is_modulo: "
    47. << std::numeric_limits<char32_t>::is_modulo << std::endl;
    48. std::cout << "std::numeric_limits::is_modulo: "
    49. << std::numeric_limits<short>::is_modulo << std::endl;
    50. std::cout << "std::numeric_limits::is_modulo: "
    51. << std::numeric_limits<unsigned short>::is_modulo << std::endl;
    52. std::cout << "std::numeric_limits::is_modulo: "
    53. << std::numeric_limits<int>::is_modulo << std::endl;
    54. std::cout << "std::numeric_limits::is_modulo: "
    55. << std::numeric_limits<unsigned int>::is_modulo << std::endl;
    56. std::cout << "std::numeric_limits::is_modulo: "
    57. << std::numeric_limits<long>::is_modulo << std::endl;
    58. std::cout << "std::numeric_limits::is_modulo: "
    59. << std::numeric_limits<unsigned long>::is_modulo << std::endl;
    60. std::cout << "std::numeric_limits::is_modulo: "
    61. << std::numeric_limits<long long>::is_modulo << std::endl;
    62. std::cout << "std::numeric_limits::is_modulo: "
    63. << std::numeric_limits<unsigned long long>::is_modulo << std::endl;
    64. std::cout << "std::numeric_limits::is_modulo: "
    65. << std::numeric_limits<float>::is_modulo << std::endl;
    66. std::cout << "std::numeric_limits::is_modulo: "
    67. << std::numeric_limits<double>::is_modulo << std::endl;
    68. std::cout << "std::numeric_limits::is_modulo: "
    69. << std::numeric_limits<long double>::is_modulo << std::endl;
    70. std::cout << "std::numeric_limits::is_modulo: "
    71. << std::numeric_limits<std::string>::is_modulo << std::endl;
    72. std::cout << "std::numeric_limits::is_modulo: "
    73. << std::numeric_limits<SName>::is_modulo << std::endl;
    74. std::cout << "std::numeric_limits::is_modulo: "
    75. << std::numeric_limits<SPartSpec>::is_modulo << std::endl;
    76. return 0;
    77. }

    输出

    能无更改地表示的 radix 位数

    std::numeric_limits<T>::digits

    static const int digits;

    (C++11 前)

    static constexpr int digits;

    (C++11 起)

     std::numeric_limits::digits 的值是能无更改地表示类型 T 的 radix 底位数。对于整数类型,这是不含符号位和填充位(若存在)的位数。对于浮点类型,这是尾数的位数。

    标准特化

    Tstd::numeric_limits::digits 的值(假设无填充位)
    /* non-specialized */​0​
    bool1
    charCHAR_BIT - std::numeric_limits::is_signed
    signed charCHAR_BIT - 1
    unsigned charCHAR_BIT
    wchar_tCHAR_BIT*sizeof(wchar_t) - std::numeric_limits::is_signed
    char8_tCHAR_BIT
    char16_tCHAR_BIT*sizeof(char16_t)
    char32_tCHAR_BIT*sizeof(char32_t)
    shortCHAR_BIT*sizeof(short)-1
    unsigned shortCHAR_BIT*sizeof(short)
    intCHAR_BIT*sizeof(int)-1
    unsigned intCHAR_BIT*sizeof(int)
    longCHAR_BIT*sizeof(long)-1
    unsigned longCHAR_BIT*sizeof(long)
    long longCHAR_BIT*sizeof(long long)-1
    unsigned long longCHAR_BIT*sizeof(long long)
    floatFLT_MANT_DIG
    doubleDBL_MANT_DIG
    long doubleLDBL_MANT_DIG

    调用示例

    1. #include <iostream>
    2. #include <string>
    3. #include <limits>
    4. #include <cstdint>
    5. struct SName
    6. {
    7. };
    8. //偏特化
    9. struct SPartSpec
    10. {
    11. };
    12. namespace std
    13. {
    14. template<>
    15. struct numeric_limits<SPartSpec>
    16. {
    17. static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true;
    18. static _GLIBCXX_USE_CONSTEXPR bool is_signed = true;
    19. static _GLIBCXX_USE_CONSTEXPR bool is_integer = true;
    20. static _GLIBCXX_USE_CONSTEXPR bool is_exact = true;
    21. static _GLIBCXX_USE_CONSTEXPR bool has_infinity = true;
    22. static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = true;
    23. static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = true;
    24. static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm = denorm_present;
    25. static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = true;
    26. static _GLIBCXX_USE_CONSTEXPR float_round_style round_style = round_toward_neg_infinity;
    27. static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = true;
    28. static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true;
    29. static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true;
    30. static _GLIBCXX_USE_CONSTEXPR int digits = CHAR_BIT;
    31. };
    32. }
    33. int main()
    34. {
    35. std::cout << std::boolalpha;
    36. std::cout << "std::numeric_limits::digits: "
    37. << std::numeric_limits<bool>::digits << std::endl;
    38. std::cout << "std::numeric_limits::digits: "
    39. << std::numeric_limits<char>::digits << std::endl;
    40. std::cout << "std::numeric_limits::digits: "
    41. << std::numeric_limits<signed char>::digits << std::endl;
    42. std::cout << "std::numeric_limits::digits: "
    43. << std::numeric_limits<unsigned char>::digits << std::endl;
    44. std::cout << "std::numeric_limits::digits: "
    45. << std::numeric_limits<wchar_t>::digits << std::endl;
    46. std::cout << "std::numeric_limits::digits: "
    47. << std::numeric_limits<char16_t>::digits << std::endl;
    48. std::cout << "std::numeric_limits::digits: "
    49. << std::numeric_limits<char32_t>::digits << std::endl;
    50. std::cout << "std::numeric_limits::digits: "
    51. << std::numeric_limits<short>::digits << std::endl;
    52. std::cout << "std::numeric_limits::digits: "
    53. << std::numeric_limits<unsigned short>::digits << std::endl;
    54. std::cout << "std::numeric_limits::digits: "
    55. << std::numeric_limits<int>::digits << std::endl;
    56. std::cout << "std::numeric_limits::digits: "
    57. << std::numeric_limits<unsigned int>::digits << std::endl;
    58. std::cout << "std::numeric_limits::digits: "
    59. << std::numeric_limits<long>::digits << std::endl;
    60. std::cout << "std::numeric_limits::digits: "
    61. << std::numeric_limits<unsigned long>::digits << std::endl;
    62. std::cout << "std::numeric_limits::digits: "
    63. << std::numeric_limits<long long>::digits << std::endl;
    64. std::cout << "std::numeric_limits::digits: "
    65. << std::numeric_limits<unsigned long long>::digits << std::endl;
    66. std::cout << "std::numeric_limits::digits: "
    67. << std::numeric_limits<float>::digits << std::endl;
    68. std::cout << "std::numeric_limits::digits: "
    69. << std::numeric_limits<double>::digits << std::endl;
    70. std::cout << "std::numeric_limits::digits: "
    71. << std::numeric_limits<long double>::digits << std::endl;
    72. std::cout << "std::numeric_limits::digits: "
    73. << std::numeric_limits<std::string>::digits << std::endl;
    74. std::cout << "std::numeric_limits::digits: "
    75. << std::numeric_limits<SName>::digits << std::endl;
    76. std::cout << "std::numeric_limits::digits: "
    77. << std::numeric_limits<SPartSpec>::digits << std::endl;
    78. return 0;
    79. }
    80. int is_modulo()
    81. {
    82. std::cout << std::boolalpha;
    83. std::cout << "std::numeric_limits::is_modulo: "
    84. << std::numeric_limits<bool>::is_modulo << std::endl;
    85. std::cout << "std::numeric_limits::is_modulo: "
    86. << std::numeric_limits<char>::is_modulo << std::endl;
    87. std::cout << "std::numeric_limits::is_modulo: "
    88. << std::numeric_limits<signed char>::is_modulo << std::endl;
    89. std::cout << "std::numeric_limits::is_modulo: "
    90. << std::numeric_limits<unsigned char>::is_modulo << std::endl;
    91. std::cout << "std::numeric_limits::is_modulo: "
    92. << std::numeric_limits<wchar_t>::is_modulo << std::endl;
    93. std::cout << "std::numeric_limits::is_modulo: "
    94. << std::numeric_limits<char16_t>::is_modulo << std::endl;
    95. std::cout << "std::numeric_limits::is_modulo: "
    96. << std::numeric_limits<char32_t>::is_modulo << std::endl;
    97. std::cout << "std::numeric_limits::is_modulo: "
    98. << std::numeric_limits<short>::is_modulo << std::endl;
    99. std::cout << "std::numeric_limits::is_modulo: "
    100. << std::numeric_limits<unsigned short>::is_modulo << std::endl;
    101. std::cout << "std::numeric_limits::is_modulo: "
    102. << std::numeric_limits<int>::is_modulo << std::endl;
    103. std::cout << "std::numeric_limits::is_modulo: "
    104. << std::numeric_limits<unsigned int>::is_modulo << std::endl;
    105. std::cout << "std::numeric_limits::is_modulo: "
    106. << std::numeric_limits<long>::is_modulo << std::endl;
    107. std::cout << "std::numeric_limits::is_modulo: "
    108. << std::numeric_limits<unsigned long>::is_modulo << std::endl;
    109. std::cout << "std::numeric_limits::is_modulo: "
    110. << std::numeric_limits<long long>::is_modulo << std::endl;
    111. std::cout << "std::numeric_limits::is_modulo: "
    112. << std::numeric_limits<unsigned long long>::is_modulo << std::endl;
    113. std::cout << "std::numeric_limits::is_modulo: "
    114. << std::numeric_limits<float>::is_modulo << std::endl;
    115. std::cout << "std::numeric_limits::is_modulo: "
    116. << std::numeric_limits<double>::is_modulo << std::endl;
    117. std::cout << "std::numeric_limits::is_modulo: "
    118. << std::numeric_limits<long double>::is_modulo << std::endl;
    119. std::cout << "std::numeric_limits::is_modulo: "
    120. << std::numeric_limits<std::string>::is_modulo << std::endl;
    121. std::cout << "std::numeric_limits::is_modulo: "
    122. << std::numeric_limits<SName>::is_modulo << std::endl;
    123. std::cout << "std::numeric_limits::is_modulo: "
    124. << std::numeric_limits<SPartSpec>::is_modulo << std::endl;
    125. return 0;
    126. }

    输出

    能无更改地表示的十进制位数

    std::numeric_limits<T>::digits10

    static const int digits10;

    (C++11 前)

    static constexpr int digits10

    (C++11 起)

    std::numeric_limits::digits10 的值是类型 T 能无更改地表示的底 10 位数,即任何拥有这么多十进制有效数字的数能转换成 T 的值并转换回十进制形式,而不因舍入或上溢而更改。对于底 radix 类型,它是 digits (对于浮点类型是 digits-1 )的值乘 log
    10(radix) 并向下取整。

    标准特化

    Tstd::numeric_limits::digits10 的值
    /* non-specialized */​0​
    bool​0​
    charstd::numeric_limits::digits * std::log10(2)
    signed charstd::numeric_limits::digits * std::log10(2)
    unsigned charstd::numeric_limits::digits * std::log10(2)
    wchar_tstd::numeric_limits::digits * std::log10(2)
    char8_tstd::numeric_limits::digits * std::log10(2)
    char16_tstd::numeric_limits::digits * std::log10(2)
    char32_tstd::numeric_limits::digits * std::log10(2)
    shortstd::numeric_limits::digits * std::log10(2)
    unsigned shortstd::numeric_limits::digits * std::log10(2)
    intstd::numeric_limits::digits * std::log10(2)
    unsigned intstd::numeric_limits::digits * std::log10(2)
    longstd::numeric_limits::digits * std::log10(2)
    unsigned longstd::numeric_limits::digits * std::log10(2)
    long longstd::numeric_limits::digits * std::log10(2)
    unsigned long longstd::numeric_limits::digits * std::log10(2)
    floatFLT_DIG /* IEEE float 为 6 */
    doubleDBL_DIG /* IEEE double 为 15 */
    long doubleLDBL_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 位的舍入回环。

    调用示例

    1. #include <iostream>
    2. #include <string>
    3. #include <limits>
    4. #include <cstdint>
    5. struct SName
    6. {
    7. };
    8. //偏特化
    9. struct SPartSpec
    10. {
    11. };
    12. namespace std
    13. {
    14. template<>
    15. struct numeric_limits<SPartSpec>
    16. {
    17. static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true;
    18. static _GLIBCXX_USE_CONSTEXPR bool is_signed = true;
    19. static _GLIBCXX_USE_CONSTEXPR bool is_integer = true;
    20. static _GLIBCXX_USE_CONSTEXPR bool is_exact = true;
    21. static _GLIBCXX_USE_CONSTEXPR bool has_infinity = true;
    22. static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = true;
    23. static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = true;
    24. static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm = denorm_present;
    25. static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = true;
    26. static _GLIBCXX_USE_CONSTEXPR float_round_style round_style = round_toward_neg_infinity;
    27. static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = true;
    28. static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true;
    29. static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true;
    30. static _GLIBCXX_USE_CONSTEXPR int digits = CHAR_BIT;
    31. static _GLIBCXX_USE_CONSTEXPR int digits10 = CHAR_BIT;
    32. };
    33. }
    34. int main()
    35. {
    36. std::cout << std::boolalpha;
    37. std::cout << "std::numeric_limits::digits10: "
    38. << std::numeric_limits<bool>::digits10 << std::endl;
    39. std::cout << "std::numeric_limits::digits10: "
    40. << std::numeric_limits<char>::digits10 << std::endl;
    41. std::cout << "std::numeric_limits::digits10: "
    42. << std::numeric_limits<signed char>::digits10 << std::endl;
    43. std::cout << "std::numeric_limits::digits10: "
    44. << std::numeric_limits<unsigned char>::digits10 << std::endl;
    45. std::cout << "std::numeric_limits::digits10: "
    46. << std::numeric_limits<wchar_t>::digits10 << std::endl;
    47. std::cout << "std::numeric_limits::digits10: "
    48. << std::numeric_limits<char16_t>::digits10 << std::endl;
    49. std::cout << "std::numeric_limits::digits10: "
    50. << std::numeric_limits<char32_t>::digits10 << std::endl;
    51. std::cout << "std::numeric_limits::digits10: "
    52. << std::numeric_limits<short>::digits10 << std::endl;
    53. std::cout << "std::numeric_limits::digits10: "
    54. << std::numeric_limits<unsigned short>::digits10 << std::endl;
    55. std::cout << "std::numeric_limits::digits10: "
    56. << std::numeric_limits<int>::digits10 << std::endl;
    57. std::cout << "std::numeric_limits::digits10: "
    58. << std::numeric_limits<unsigned int>::digits10 << std::endl;
    59. std::cout << "std::numeric_limits::digits10: "
    60. << std::numeric_limits<long>::digits10 << std::endl;
    61. std::cout << "std::numeric_limits::digits10: "
    62. << std::numeric_limits<unsigned long>::digits10 << std::endl;
    63. std::cout << "std::numeric_limits::digits10: "
    64. << std::numeric_limits<long long>::digits10 << std::endl;
    65. std::cout << "std::numeric_limits::digits10: "
    66. << std::numeric_limits<unsigned long long>::digits10 << std::endl;
    67. std::cout << "std::numeric_limits::digits10: "
    68. << std::numeric_limits<float>::digits10 << std::endl;
    69. std::cout << "std::numeric_limits::digits10: "
    70. << std::numeric_limits<double>::digits10 << std::endl;
    71. std::cout << "std::numeric_limits::digits10: "
    72. << std::numeric_limits<long double>::digits10 << std::endl;
    73. std::cout << "std::numeric_limits::digits10: "
    74. << std::numeric_limits<std::string>::digits10 << std::endl;
    75. std::cout << "std::numeric_limits::digits10: "
    76. << std::numeric_limits<SName>::digits10 << std::endl;
    77. std::cout << "std::numeric_limits::digits10: "
    78. << std::numeric_limits<SPartSpec>::digits10 << std::endl;
    79. return 0;
    80. }

    输出

  • 相关阅读:
    RabbitMQ —— 初窥门径
    使用kotlin用回溯法解决电话号码的字母组合问题
    Day17:稀疏数组的超细详解
    Android Jetpack 中Hilt的使用
    Linux学习-63-源码包服务管理方法
    认识微服务
    Android高德地图截屏功能(可包含自定义控件)
    详谈动态规划问题并解最大子数组和
    MongoDB集合结构分析工具Variety
    计算机操作系统 第四章 存储器管理(3)
  • 原文地址:https://blog.csdn.net/qq_40788199/article/details/133654998