...世界上最受推崇和专业设计的 C++ 库项目之一。
— Herb Sutter and Andrei Alexandrescu, C++ Coding Standards
当然,这样的列表不可能让每个人都满意。
我们使用的一些标准是
(如果觉得方便,您可以轻松定义自己的常数,例如: FPT one =static_cast<FPT>(42);
)。
所有常数都是使用高精度软件计算出来的,精度高达 300 位,约 100 位十进制数字。(精度可以任意选择,仅受计算时间限制)。
选择的最小精度(100 位十进制数字)超过了可合理预见的浮点硬件(256 位)的精度,应该可以满足大多数高精度计算。
long double epsilon
。![]() |
警告 |
---|---|
我们尚未能够检查所有常数在完全任意精度(目前为 100 位十进制数字)下都是准确的。但是某些关键值(如 |
即使在使用具有不同精度的不同浮点类型时,使用数学常数编写的代码也很容易移植。
期望计算结果完全相同是错误的,但您可以为正在使用的浮点类型实现尽可能最佳的精度。
这对用户没有额外的成本,但减少了由浮点计算的内在有限精度引起的令人烦恼、通常令人困惑且非常难以追踪的效果。
这种限制的一个无害症状是虚假的最低有效位;最坏的情况是,稍微不准确的常数有时会导致迭代算法发散,因为内部比较失败。
有关正常用法,请参阅上面的教程,但本常见问题解答解释了常数使用的内部细节。
常数存储为 100 位十进制数字值。但是,某些编译器不接受这么长的十进制数字字符串。因此,常数被分成两部分,第一部分包含至少 128 位 long double 精度(35 位十进制数字),为了保持一致性,应采用科学计数法,并带有符号指数。
第二部分是以字符串字面量形式表示的常数值,精度至少为 100 位十进制数字(实际上意味着至少 102 位数字)。为了保持一致性,再次使用科学计数法,并带有符号指数。
对于精度大于 long double 的类型,如果 T 可从 const char*
构造,则直接从字符串构造,否则我们回退到 lexical_cast 以转换为类型 T
。(使用字符串是必要的,因为您不能使用数字常数,因为即使是 long double
也可能没有足够的位数)。
因此,例如,像 pi 这样的常数在内部定义为
BOOST_DEFINE_MATH_CONSTANT(pi, 3.141592653589793238462643383279502884e+00, "3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651e+00");
在这种情况下,有效位数为 109 位十进制数字,确保 100 位十进制数字是精确的,指数为零。
请参阅定义新常数以计算新常数。
这样的宏定义可以粘贴到用户代码中方便的位置,或者如果添加到 Boost.Math 库中,则可以粘贴到 boost/math/constants.hpp
中。
除了内置的浮点类型 float
、double
、long double
之外,还有几个任意精度的浮点类可用,但大多数未获得商业用途许可。
这是一个维护良好且功能齐全的库,它提供了许多高精度类型,以及到其他流行库(如 MPFR)的包装器。
NTL by Victor Shoup 具有固定和任意高精度固定和浮点类型。但是,这些都未获得商业用途许可。
#include <NTL/quad_float.h> // quad precision 106-bit, about 32 decimal digits. using NTL::to_quad_float; // Less precise than arbitrary precision NTL::RR.
NTL 类 quad_float
,它提供了一种四倍精度的形式,106 位有效位数(但没有扩展的指数范围)。对于 IEC559/IEEE 754 兼容处理器,例如 Intel X86 系列,具有 64 位 double 和 53 位有效位数,使用两个 64 位 double 的有效位数,如果 std::numeric_limits<double>::digits10
为 16,那么我们得到的精度大约是两倍,因此 std::numeric_limits<quad_float>::digits10()
应该是 32。(默认的 std::numeric_limits<RR>::digits10()
应该约为 40)。(这似乎与实验结果一致)。我们通过添加 2 或 3 个额外的十进制数字来输出常数(包括一些噪声位,std::numeric_limits<RR>::max_digits10()
的近似值),因此使用 quad_float::SetOutputPrecision(32 + 3);
Apple Mac/Darwin 对其内置的 long double
类型使用类似的 doubledouble 106 位。
![]() |
注意 |
---|---|
所有 |
新项目应使用 Boost.Multiprecision。
使用 NTL 类 RR 的任意精度浮点数,默认值为 150 位(约 50 位十进制数字),此处使用 300 位输出 100 位十进制数字,足以满足许多实际的非“数论” C++ 应用程序。
NTL 数论库未获得商业用途许可。
此类在 Boost.Math 中使用,并且是在使用 big_number 项目计算新数学常数时的一个选项。
新项目应使用 Boost.Multiprecision。
GMP 和 MPFR 也已用于计算常数,但根据 Lesser GPL 许可获得许可,未获得商业用途许可。
一项审查得出结论,常数的呈现方式未能满足许多人的需求。当时提出的所有方法均未满足许多用户的基本要求,即允许简单地编写 pi
而不是 pi()
。许多科学和工程方程看起来难以阅读,因为函数调用括号可能会与通常需要的许多其他括号混淆。当时提出的所有避免括号的方法都未能满足所有需求,通常是由于复杂性以及不适用于各种实际情况。
因此,简单的命名空间方法(单独提出,但在第一次审查中被拒绝)已被添加,以允许用户方便地访问 float
、double
和 long double
值,但与模板结构和函数结合使用,以允许与其他非内置浮点类型同时使用。
Boost.Math 的早期版本提供了函数机制。
新机制是为了允许部分特化。请参阅上面的“自定义特化常数”。它还应该允许与其他软件包(如 ttmath Bignum C++ 库)一起使用。
不在这里,因为物理常数
某些物理常数可能在 Boost.Units 中可用。