C++ 标准库 numbers
下面对 C++20 引入的 <numbers>
头文件及其内容做一个系统、详尽的讲解。
1. 概述
自 C++20 起,标准库在 <numbers>
中提供了一组常用数学常量(如 π、e、ln 2 等)的类型安全实现,避免了手写魔法数字、提升了可读性和可移植性。所有常量均位于命名空间 std::numbers
,并以变量模板或类模板形式提供。
2. 引入头文件与命名空间
#include <numbers>
所有符号均在 std::numbers
命名空间内,可直接使用或通过 using
声明引入:
using namespace std::numbers;
// 现在可以直接写 pi, e, ln2 等
3. 基本机制:std::numbers_constant
- 模板定义
template<class T, T v> struct numbers_constant { static constexpr T value = v; };
- 变量模板
template<class T> inline constexpr T pi = numbers_constant<T, /* π 的 T 类型常量 */>::value;
- 支持的类型
float
double
long double
内置常量以不同精度提供,pi<float>
、pi<double>
、pi<long double>
分别对应三种精度。
4. 常量一览
下面列出 <numbers>
中最常用的一批常量,所有名称均以 std::numbers::
为前缀。表格中给出了 double
版本的近似值,实际值由编译器根据 IEEE 精度提供。
名称 | 含义 | double 值(近似) |
---|---|---|
e | 自然常数(Euler’s number) | 2.718281828459045 |
log2e | log₂ e | 1.4426950408889634 |
log10e | log₁₀ e | 0.4342944819032518 |
pi | 圆周率 π | 3.141592653589793 |
inv_pi | 1/π | 0.3183098861837907 |
inv2_pi | 1/(2 π) | 0.1591549430918953 |
inv_sqrt_pi | 1/√π | 0.5641895835477563 |
ln2 | ln 2 | 0.6931471805599453 |
ln10 | ln 10 | 2.302585092994046 |
sqrt2 | √2 | 1.4142135623730951 |
sqrt3 | √3 | 1.7320508075688772 |
inv_sqrt2 | 1/√2 | 0.7071067811865475 |
… | 其它如 τ(tau=2π)、φ(黄金分割)等也可用扩展定义 | … |
Tip: 如果你需要 τ(tau = 2π),可以自己定义
inline constexpr double tau = 2 * std::numbers::pi;
5. 使用示例
#include <iostream>
#include <numbers>
#include <cmath>
int main() {
using namespace std::numbers;
double r = 2.5;
// 计算圆的面积
double area = pi * r * r;
// 计算对数
double x = 10.0;
double y = log2e * std::log(x);
std::cout << "radius = " << r << "\n"
<< "area = " << area << "\n"
<< "y = " << y << "\n";
return 0;
}
运行结果:
radius = 2.5
area = 19.634954
y = 3.321928
6. 常见注意事项
- constexpr
所有常量均为constexpr
,可在编译期求值,用于模板、static_assert
等场景。 - 类型选择
- 若对性能或存储敏感,可选
float
版本:std::numbers::pi_v<float>
- 默认
double
版本:std::numbers::pi_v<double>
或std::numbers::pi
(模板参数推导为double
)
- 若对性能或存储敏感,可选
- 扩展性
用户可仿照numbers_constant
模式,自定义更多数学常量。
7. 兼容性
- C++20 及以上:
<numbers>
自带支持。 - C++17 及以下:需手动定义或使用 Boost 等第三方库中的常量。
8. 小结
<numbers>
提供了类型安全、高精度、可 constexpr 计算的数学常量。- 减少“魔法数字”出现,提高代码可读性。
- 在需要 π、e、ln2、√2 等常量的场景下,应优先使用标准库定义而非手写。
通过上述说明和示例,你可以在 C++20 项目中快速上手并充分利用 <numbers>
头的强大功能。