C++ 中 std::numeric_limits使用详解
一、std::numeric_limits
基本概念
std::numeric_limits
是 C++ 标准库 <limits>
中提供的模板类,用于 查询各种数值类型的特性和边界值,支持所有基本算术类型(整型、浮点型)以及自定义类型(如果你为自定义类型实现了特化)。
#include <limits>
#include <iostream>int main() {std::cout << "int max: " << std::numeric_limits<int>::max() << "\n";std::cout << "double min: " << std::numeric_limits<double>::min() << "\n";std::cout << "double epsilon: " << std::numeric_limits<double>::epsilon() << "\n";
}
说明:
std::numeric_limits<T>
是一个模板类。T
可以是内置类型或你自定义特化的类型。- 它提供静态成员函数和常量来查询类型特性。
二、主要成员函数/常量详解
我按照类别整理,便于理解和查找。
1. 边界值和极限
成员 | 说明 | 示例 |
---|---|---|
min() | 对于整数类型是最小值(负数最小),对于浮点类型是 最小正归一化值 | std::numeric_limits<float>::min() |
max() | 最大可表示值 | std::numeric_limits<int>::max() |
lowest() | 最低值(浮点数负最大值) | std::numeric_limits<double>::lowest() |
注意:
-
对浮点数,
min()
和lowest()
不一样:min()
→ 最小正值lowest()
→ 最小可表示负值
std::cout << std::numeric_limits<float>::min() << "\n"; // 1.17549e-38
std::cout << std::numeric_limits<float>::lowest() << "\n"; // -3.40282e38
2. 精度与机器误差
成员 | 说明 |
---|---|
epsilon() | 浮点数精度,即 1.0 与大于 1.0 的最小可表示值差 |
digits | 类型能表示的有效二进制位数 |
digits10 | 类型能表示的有效十进制位数 |
max_digits10 | 精确表示浮点值所需十进制位数 |
double eps = std::numeric_limits<double>::epsilon(); // 约 2.22e-16
应用:
- 在 SLAM 残差计算或优化中,判断浮点相等时常用
epsilon()
:
if (fabs(x - y) < std::numeric_limits<double>::epsilon()) { ... }
3. 特殊值支持(浮点类型)
成员 | 说明 |
---|---|
has_infinity | 是否支持 +∞ |
infinity() | 返回正无穷 |
has_quiet_NaN | 是否支持 NaN(静默 NaN) |
quiet_NaN() | 返回 NaN |
signaling_NaN() | 返回信号 NaN(会触发异常) |
has_denorm | 是否支持非归一化值 |
denorm_min() | 返回最小非归一化值 |
double inf = std::numeric_limits<double>::infinity();
double nan = std::numeric_limits<double>::quiet_NaN();
4. 类型特性(布尔值)
成员 | 说明 |
---|---|
is_signed | 是否有符号 |
is_integer | 是否整数类型 |
is_exact | 是否精确(整型通常为 true,浮点型为 false) |
is_modulo | 整数溢出行为是否按模运算(环绕) |
is_bounded | 是否有上下边界 |
is_specialized | 是否为标准类型提供特化(几乎所有内置类型为 true) |
5. 可移植性/类型信息
成员 | 说明 |
---|---|
radix | 数值基底(通常 2) |
round_style | 四舍五入模式,0=未定义,1=向零,2=向最近,3=向正无穷,4=向负无穷 |
traps | 是否会产生异常或陷阱 |
tinyness_before | 判断非归一化数是否在下溢前被截断 |
三、示例:整数类型与浮点类型对比
#include <iostream>
#include <limits>
#include <iomanip>int main() {std::cout << "int max: " << std::numeric_limits<int>::max() << "\n";std::cout << "int min: " << std::numeric_limits<int>::min() << "\n";std::cout << "float max: " << std::numeric_limits<float>::max() << "\n";std::cout << "float min (positive): " << std::numeric_limits<float>::min() << "\n";std::cout << "float lowest: " << std::numeric_limits<float>::lowest() << "\n";std::cout << "float epsilon: " << std::numeric_limits<float>::epsilon() << "\n";std::cout << "float infinity: " << std::numeric_limits<float>::infinity() << "\n";std::cout << "float NaN: " << std::numeric_limits<float>::quiet_NaN() << "\n";
}
输出示例(不同平台略有差异):
int max: 2147483647
int min: -2147483648
float max: 3.40282e+38
float min (positive): 1.17549e-38
float lowest: -3.40282e+38
float epsilon: 1.19209e-07
float infinity: inf
float NaN: nan
四、常见高级用法
1. 在残差阈值、鲁棒优化中的应用
#include <limits>double r = computeResidual();
double threshold = std::numeric_limits<double>::max(); // 理论上可设置为最大值
if (r > threshold) {// 超过可表示范围,判为异常
}
2. 判断数值类型特性
#include <limits>
#include <iostream>
#include <type_traits>template<typename T>
void printTypeInfo() {std::cout << "is_signed: " << std::numeric_limits<T>::is_signed << "\n";std::cout << "is_integer: " << std::numeric_limits<T>::is_integer << "\n";std::cout << "is_exact: " << std::numeric_limits<T>::is_exact << "\n";
}printTypeInfo<int>();
printTypeInfo<float>();
3. 浮点比较收敛判断
double prev = 1.0, curr = 1.0 + 1e-16;
if (std::fabs(curr - prev) < std::numeric_limits<double>::epsilon()) {std::cout << "迭代收敛!\n";
}
4. 初始化最小/最大残差
double r_min = std::numeric_limits<double>::lowest();
double r_max = std::numeric_limits<double>::lowest(); // 或 max() 用于上界
5. 使用 NaN 标记异常点
double r = computeResidual(point_error);
if (std::isnan(r) || r > 1e6) {r = std::numeric_limits<double>::quiet_NaN(); // 标记异常
}
6. 泛型模板安全编程
template<typename T>
void printLimits() {std::cout << "max: " << std::numeric_limits<T>::max() << "\n";std::cout << "min: " << std::numeric_limits<T>::min() << "\n";std::cout << "epsilon: " << std::numeric_limits<T>::epsilon() << "\n";
}printLimits<float>();
printLimits<double>();
五、注意事项和坑
-
min()
对浮点类型不是最小负数- 使用
lowest()
获取最小负数。
- 使用
-
epsilon()
不等于 0- 仅用于浮点数相等判断,不是绝对误差阈值。
-
自定义类型必须特化
- 如果你为 Eigen 或自定义标量类型定义 numeric_limits,必须实现所有静态成员。
-
不同平台浮点实现略有差异
- IEEE 754 基本一致,但极端情况下可能略有差异。
-
整数溢出
max()
+ 1 会溢出(按类型is_modulo
判断),不要盲目加减。
六、总结
-
std::numeric_limits
是查询类型极值、精度、特殊值和特性的万能工具。 -
对 浮点残差计算、鲁棒优化、边界值判断 非常重要。
-
包含的功能主要分为:
- 边界值(min/max/lowest)
- 精度(epsilon/digits)
- 特殊值(inf/NaN/denorm)
- 类型属性(is_signed/is_integer/is_exact)
-
可用于 跨平台、泛型编程,尤其适合模板 SLAM/优化库设计。