C/C++数值计算时常需要用到诸如Pi、自然常数e等数学常量,但是这些常量并没有在标准C/C++中定义。幸运的是,现代化的C/C++ math.h 都定义了如下常用的数学常量:

符号表达式
M_Ee2.71828182845904523536
M_LOG2Elog2(e)1.44269504088896340736
M_LOG10Elog10(e)0.434294481903251827651
M_LN2ln(2)0.693147180559945309417
M_LN10ln(10)2.30258509299404568402
M_PIpi3.14159265358979323846
M_PI_2pi/21.57079632679489661923
M_PI_4pi/40.785398163397448309616
M_1_PI1/pi0.318309886183790671538
M_2_PI2/pi0.636619772367581343076
M_2_SQRTPI2/sqrt(pi)1.12837916709551257390
M_SQRT2sqrt(2)1.41421356237309504880
M_SQRT1_21/sqrt(2)0.707106781186547524401

需要注意的是,Windows平台上的MSVC编译器,使用这些数学常量需要先定义 _USE_MATH_DEFINES 宏,否则会报未定义的错误:

#define _USE_MATH_DEFINES // C++
#include <cmath>

#define _USE_MATH_DEFINES // C
#include <math.h>

到了C++20,事情有了新的变化:新增的 numbers 头文件将这些常量都定义了,并且无需以 M_ 修饰。得益于C++ 14中新增的 变量模板 特性,这些数学常量都以模板的形式定义:

#include <iostream>
#include <iomanip>
#include <numbers>
#include <limits>

int main() {
  // 输出单精度的pi
  std::cout << "float pi: " << std::setprecision(std::numeric_limits<float>::digits10) << std::numbers::pi_v<float> << std::endl;
  // std::numbers::pi 是double类型的特化
  // std::numbers::pi 等同于 std::numbers::pi_v<double>
  std::cout << "double pi: " << std::setprecision(std::numeric_limits<double>::digits10) << std::numbers::pi << std::endl;

  // 双精度的ln(2)
  std::cout << "double ln2: " << std::numbers::ln2 << std::endl;
  return 0;
}

至此,我们可以放心地使用数学常量而无需担心跨平台问题了。

参考

1. Math constants

2. Predefined Mathematical Constants

3. Mathematical constants

4. C++模板编程