Oracle® Developer Studio 12.5:数值计算指南

退出打印视图

更新时间: 2016 年 6 月
 
 

3.6 libmlibsunmath 的实现功能

本节介绍了 libmlibsunmath 的实现功能:

  • 使用无限精确 ?? 的参数约简以及按 ?? 缩放的三角函数

  • 用于在 IEEE 和非 IEEE 格式之间转换浮点数据的数据转换例程

  • 随机数生成器

3.6.1 关于算法

在基于 SPARC 的系统上,libmlibsunmath 中的初等函数是使用表驱动算法和多项式/有理数近似算法的组合实现的。所发布的这些算法不断变化,以实现更高的性能或精确度。在基于 x86 的系统上,libmlibsunmath 中的某些初等函数是使用 x86 指令集中提供的初等函数内核指令实现的;其他函数是用基于 SPARC 的系统上使用的相同表驱动算法或多项式/有理数近似算法实现的。

libm 中常见初等函数及 libsunmath 中常见单精度初等函数的表驱动算法和多项式/有理数近似算法都将准确结果传送到最后位置单元 (unit in last place, ulp) 内。 在基于 SPARC 的系统上,libsunmath 中的常见四倍精度初等函数将精确结果传送到一个 ulp 内,但是 expm1llog1pl 函数除外,它们将精确结果传送到两个 ulps 内。(常见函数包括指数函数、对数函数、幂函数和弧度参数的循环三角函数。其他函数,如双曲三角函数和高等超越函数是不精确的。)通过运算法则直接分析获取这些误差界限。用户通过使用 BeEF(Berkeley Elementary Function 测试程序)也能检测这些例程的精确度,可以从 ucbtest 软件包中的 netlib 获得该程序,网址为 http://www.netlib.org/fp/ucbtest.tgzhttp://www.netlib.org/fp/ucbtest.tgz

3.6.2 三角函数的参数约简

弧度参数在 [–??/4,??/4] 范围之外的三角函数通常可通过将参数约简到指定范围(减去 ??/2 的整数倍)来进行计算。

因为 ?? 不是计算机可表示的数字,所以对其求近似值。三角函数的最终计算中的误差取决于参数约简中造成的舍入误差(使用近似的 ?? 值和舍入值)以及计算使用约简参数的三角函数时的近似误差。即使是非常小的参数,最终结果的相对误差可能取决于该参数的约简误差;而对于较大的参数,参数约简造成的误差可能并不比其他误差大。

通常,人们误认为所有使用大参数的三角函数本身准确性很低,而所有小参数的准确性相对高一些。这是基于简单的观察:计算机可表示的非常大的数字是由大于 ?? 的距离分隔的。

计算的三角函数值没有准确性突然变差的内在界限,不准确的函数值也没有变得无法使用的内在界限。假设参数始终不断进行约简,实际上很难发现使用 ?? 近似值完成的参数约简这一情况,这是因为为大参数和小参数都保留了所有基本的恒等式和关系。

libmlibsunmath 三角函数使用“无限”精确的 ?? 进行参数约简。 将值 2/?? 的计算结果取 916 位十六进制数字,并将其存储在查找表中以在参数约简过程中使用。

sinpicospitanpi 函数组(请参见表 16)使用 ?? 来对输入参数进行缩放,以避免由于范围约简而产生的误差。

3.6.3 数据转换例程

libmlibsunmath 中,有一个灵活的数据转换例程 convert_external,它用于在 IEEE 和非 IEEE 格式之间转换二进制浮点数据。

支持的格式包括 SPARC (IEEE)、IBM PC、VAX、IBM S/370 和 Cray 使用的那些格式。

有关处理 Cray 上生成的数据以及使用函数 convert_external 将数据转换为基于 SPARC 的系统上使用的 IEEE 格式的示例,请参见 convert_external(3m) 上的手册页。

3.6.4 随机数工具

可以使用三种工具来生成 32 位整数、单精度浮点和双精度浮点格式的统一伪随机数:

  • addrans(3m) 手册页中描述的函数基于表驱动的加法随机数生成器系列。

  • lcrans(3m) 手册页中介绍的函数基于线性同余随机数生成器。

  • mwcrans(3m) 手册页中介绍的函数基于进位相乘的随机数生成器。这些函数还包括以 64 位整数格式提供统一伪随机数的生成器。

此外,shufrans(3m) 手册页中介绍的函数可与其中的任何生成器结合使用以混洗伪随机数的数组,因而为需要它的应用程序提供更大的随机性。注意,没有用于混洗 64 位整数数组的工具。

每个随机数工具都包含每次生成一个随机数(即每个函数调用一个随机数)的例程以及在单个调用中生成随机数数组的例程。每次生成一个随机数的函数提供的数字位于表 30所示的范围内。

表 30  单值随机数生成器的区间
函数
下界
上界
i_addran_
-2147483648
2147483647
r_addran_
0
0.9999999403953552246
d_addran_
0
0.9999999999999998890
i_lcran_
1
2147483646
r_lcran_
4.656612873077392578E-10
1
d_lcran_
4.656612875245796923E-10
0.9999999995343387127
i_mwcran_
0
2147483647
u_mwcran_
0
4294967295
i_llmwcran_
0
9223372036854775807
u_llmwcran_
0
18446744073709551615
r_mwcran_
0
0.9999999403953552246
d_mwcran_
0
0.9999999999999998890

在单个调用中生成整个随机数数组的函数允许用户指定生成数所在的区间。示例给出了一些示例,说明如何生成在不同区间中均匀分布的随机数数组。

注意,addransmwcrans 生成器通常比 lcrans 生成器更有效,但它们的理论基础还不足够精确。S. Park 和 K. Miller 于 1988 年 10 月在《Communications of the ACM》上发表的《Random Number Generators: Good Ones Are Hard To Find》介绍了线性同余算法的原理。Knuth 编著的《The Art of Computer Programming》第 2 卷中讨论了加法的随机数生成器。