Boost C++ Libraries

...世界上最受推崇和专业设计的 C++ 库项目之一。 Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

PrevUpHomeNext

数学常数常见问题解答

为什么选择这些常数?

当然,这样的列表不可能让每个人都满意。

我们使用的一些标准是

(如果觉得方便,您可以轻松定义自己的常数,例如: FPT one =static_cast<FPT>(42);)。

常数是如何命名的?
常数是如何推导出来的?

所有常数都是使用高精度软件计算出来的,精度高达 300 位,约 100 位十进制数字。(精度可以任意选择,仅受计算时间限制)。

常数的精度如何?

选择的最小精度(100 位十进制数字)超过了可合理预见的浮点硬件(256 位)的精度,应该可以满足大多数高精度计算。

常数是如何测试的?
  1. 使用 Boost.Test BOOST_CHECK_CLOSE_FRACTION 进行比较,使用 long double 字面量,至少 35 位十进制数字,足以保证所有 long double 实现的精度。容差通常是两倍的 long double epsilon
  2. 与 long double 精度计算进行比较。由于舍入等计算噪声,这通常需要比两个 epsilon 稍高的容差,尤其是在调用三角函数和其他函数时。
  3. 与独立的已发布值进行比较,例如,使用在线整数序列百科全书 (OEIS),同样使用至少 35 位十进制数字字符串。
  4. 与使用任意精度工具(如 Mathematica)独立计算的值进行比较,同样使用至少 35 位十进制数字字面量字符串。
[Warning] 警告

我们尚未能够检查所有常数在完全任意精度(目前为 100 位十进制数字)下都是准确的。但是某些关键值(如 epi)似乎是准确的,并且内部一致性表明其他常数也具有这种精度。

为什么可移植性很重要?

即使在使用具有不同精度的不同浮点类型时,使用数学常数编写的代码也很容易移植。

期望计算结果完全相同是错误的,但您可以为正在使用的浮点类型实现尽可能最佳的精度

这对用户没有额外的成本,但减少了由浮点计算的内在有限精度引起的令人烦恼、通常令人困惑且非常难以追踪的效果。

这种限制的一个无害症状是虚假的最低有效位;最坏的情况是,稍微不准确的常数有时会导致迭代算法发散,因为内部比较失败。

常数的内部格式是什么,为什么?

有关正常用法,请参阅上面的教程,但本常见问题解答解释了常数使用的内部细节。

常数存储为 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 中。

我可以使用哪些浮点类型?

除了内置的浮点类型 floatdoublelong double 之外,还有几个任意精度的浮点类可用,但大多数未获得商业用途许可。

Boost.Multiprecision by Christopher Kormanyos and John Maddock

这是一个维护良好且功能齐全的库,它提供了许多高精度类型,以及到其他流行库(如 MPFR)的包装器。

NTL class quad_float

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 位。

[Note] 注意

所有 doubledouble 浮点类型的精度都相当奇怪,给出的值仅为近似值。

新项目应使用 Boost.Multiprecision

NTL class RR

使用 NTL 类 RR 的任意精度浮点数,默认值为 150 位(约 50 位十进制数字),此处使用 300 位输出 100 位十进制数字,足以满足许多实际的非“数论” C++ 应用程序。

NTL 数论库未获得商业用途许可

此类在 Boost.Math 中使用,并且是在使用 big_number 项目计算新数学常数时的一个选项。

新项目应使用 Boost.Multiprecision

GMP and MPFR

GMPMPFR 也已用于计算常数,但根据 Lesser GPL 许可获得许可,未获得商业用途许可

之前为 Boost 提出的常数集合发生了什么?

一项审查得出结论,常数的呈现方式未能满足许多人的需求。当时提出的所有方法均未满足许多用户的基本要求,即允许简单地编写 pi 而不是 pi()。许多科学和工程方程看起来难以阅读,因为函数调用括号可能会与通常需要的许多其他括号混淆。当时提出的所有避免括号的方法都未能满足所有需求,通常是由于复杂性以及不适用于各种实际情况。

因此,简单的命名空间方法(单独提出,但在第一次审查中被拒绝)已被添加,以允许用户方便地访问 floatdoublelong double 值,但与模板结构和函数结合使用,以允许与其他非内置浮点类型同时使用。

为什么常数(内部)使用结构而不是简单的函数?

Boost.Math 的早期版本提供了函数机制。

新机制是为了允许部分特化。请参阅上面的“自定义特化常数”。它还应该允许与其他软件包(如 ttmath Bignum C++ 库)一起使用。

在哪里可以找到其他高精度常数?
  1. 来自 Simon Plouffe 基于 Web 的集合 http://pi.lacim.uqam.ca/eng/ 的高精度和良好准确度(>40 位十进制数字)的常数。
  2. 在线整数序列百科全书 (OEIS)
  3. 使用印刷文本光学扫描的值进行检查,并从以下内容转换而来:D. E. Knuth,《计算机程序设计艺术》,附录 A,表 1,第 1 卷,ISBN 0 201 89683 4 (1997)
  4. M. Abrahamovitz & I. E. Stegun,美国国家标准局,《数学函数手册》,现在已被取代的公式参考来源,取代者为
  5. Frank W. Olver, Daniel W. Lozier, Ronald F. Boisvert, Charles W. Clark, NIST Handbook of Mathematical Functions, Cambridge University Press, ISBN 978-0-521-14063-8, 2010.
  6. John F Hart, Computer Approximations, Kreiger (1978) ISBN 0 88275 642 7.
  7. 来自 Cephes 数学库、Stephen L. Moshier 和 CALC100 100 位十进制数字复变量计算器程序(一个 DOS 实用程序)的一些值。
  8. Xavier Gourdon、Pascal Sebah,Number, constants and computation 上的 50 位十进制数字常数。
物理常数在哪里?

不在这里,因为物理常数

某些物理常数可能在 Boost.Units 中可用。


PrevUpHomeNext