78-math.h库增补
B.8.4 math.h 库增补
大部分C90数学库中都声明了 double 类型参数和 double 类型返回值的函数,例如:
double sin(double);
double sqrt(double);
C99和C11库为所有这些函数都提供了 float 类型和 long double 类型的函数。这些函数的名称由原来函数名加上 f 或 l 后缀构成,例如:
float sinf(float); /* sin()的float版本 */
long double sinl(long double); /* sin()的long double版本 */
有了这些不同精度的函数系列,用户可以根据具体情况选择最效率的类型和函数组合。
C99还新增了一些科学、工程和数学运算中常用的函数。表B.5.16列出了所有数学函数的 double 版本。在许多情况下,这些函数的返回值都可以使用现有的函数计算得出,但是新函数计算得更快更精确。例如, loglp(x) 表示的值与与 log(1 + x) 相同,但是 loglp(x) 使用了不同的算法,对于较小的 x 值而言计算更精确。因此,可以使用 log() 函数作普通运算,但是对于精确要求较高且 x 值较小时,用 loglp() 函数更好。
除这些函数以外,数学库中还定义了一些常量和与数字分类、舍入相关的函数。例如,可以把值分为无穷值、非数( NaN )、正常值、低于正常的值、真零。 [NaN 是一个特别的值,用于表示一个不是数的值。例如, asin(2.0) 返回 NaN ,因为定义了 asin() 函数的参数必须是 -1 ~ 1 范围内的值。低于正常的值是比使用全精度表示的最小值还要小的数。 ] 还有一些专用的比较函数,如果一个或多个参数是非正常值时,函数的行为与标准的关系运算符不同。
使用C99的分类方案可以检测计算的规律性。例如, math.h 中的 isnormal() 宏,如果其参数是一个正常的数,则返回真。下面的代码使用该宏在 num 不正常时结束循环:
#include <math.h> // 为了使用isnormal()
...
float num = 1.7e-19;
float numprev = num;
while (isnormal(num)) // 当num为全精度的float类型值
{
numprev = num;
num /= 13.7f;
}
简而言之,数学库为更好地控制如何计算浮点数,提供了扩展支持。