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
log2elog₂ e1.4426950408889634
log10elog₁₀ e0.4342944819032518
pi圆周率 π3.141592653589793
inv_pi1/π0.3183098861837907
inv2_pi1/(2 π)0.1591549430918953
inv_sqrt_pi1/√π0.5641895835477563
ln2ln 20.6931471805599453
ln10ln 102.302585092994046
sqrt2√21.4142135623730951
sqrt3√31.7320508075688772
inv_sqrt21/√20.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. 常见注意事项

  1. constexpr
    所有常量均为 constexpr,可在编译期求值,用于模板、static_assert 等场景。
  2. 类型选择
    • 若对性能或存储敏感,可选 float 版本:std::numbers::pi_v<float>
    • 默认 double 版本:std::numbers::pi_v<double> 或 std::numbers::pi(模板参数推导为 double
  3. 扩展性
    用户可仿照 numbers_constant 模式,自定义更多数学常量。

7. 兼容性

  • C++20 及以上<numbers> 自带支持。
  • C++17 及以下:需手动定义或使用 Boost 等第三方库中的常量。

8. 小结

  • <numbers> 提供了类型安全高精度可 constexpr 计算的数学常量。
  • 减少“魔法数字”出现,提高代码可读性。
  • 在需要 π、e、ln2、√2 等常量的场景下,应优先使用标准库定义而非手写。

通过上述说明和示例,你可以在 C++20 项目中快速上手并充分利用 <numbers> 头的强大功能。

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注