<math.h> 头文件包含了多个数学函数的原型。在 1990 年版的 ISO 标准中,仅指定了这些函数的 double 版本;1999 年版则添加了 floatlong double 版本。要使用这些数学函数,必须将程序与数学库链接。对于某些编译器(包括 GCC),你需要指定额外的参数 -lm[1][2]。

数学函数可能会产生两种类型的错误。域错误发生在函数的参数无效时,例如对 sqrt(平方根函数)传递一个负数参数。范围错误发生在函数的结果无法在特定的浮点类型中表示时,例如当 double 的最大值大约为 10308 时,pow(1000.0, 1000.0) 会导致范围错误。

这些函数可以分为以下几类:

三角函数

acosasin 函数

acos 函数返回其参数的反余弦值(弧度),asin 函数返回其参数的反正弦值(弧度)。所有这些函数的参数必须在 [-1, +1] 范围内。反余弦函数返回值的范围是 [0, π];反正弦函数返回值的范围是 [-π/2, +π/2]。

#include <math.h>
float asinf(float x); /* C99 */
float acosf(float x); /* C99 */
double asin(double x);
double acos(double x);
long double asinl(long double x); /* C99 */
long double acosl(long double x); /* C99 */

atanatan2 函数

atan 函数返回其参数的反正切值(弧度),atan2 函数返回 y/x 的反正切值(弧度)。atan 函数返回值的范围是 [-π/2, +π/2](原因是浮点数可能表示无穷大,atan(±∞) = ±π/2);atan2 函数返回值的范围是 [-π, +π]。对于 atan2,如果两个参数都是零,可能会发生域错误。

#include <math.h>
float atanf(float x); /* C99 */
float atan2f(float y, float x); /* C99 */
double atan(double x);
double atan2(double y, double x);
long double atanl(long double x); /* C99 */
long double atan2l(long double y, long double x); /* C99 */

cossintan 函数

cossintan 函数分别返回参数的余弦值、正弦值和正切值,单位为弧度。

#include <math.h>
float cosf(float x); /* C99 */
float sinf(float x); /* C99 */
float tanf(float x); /* C99 */
double cos(double x);
double sin(double x);
double tan(double x);
long double cosl(long double x); /* C99 */
long double sinl(long double x); /* C99 */
long double tanl(long double x); /* C99 */

双曲函数

coshsinhtanh 函数分别计算参数的双曲余弦、双曲正弦和双曲正切值。对于双曲正弦和双曲余弦函数,如果参数的绝对值太大,可能会发生范围错误。

acosh 函数计算参数的反双曲余弦值。如果参数小于 1,将发生域错误。

asinh 函数计算参数的反双曲正弦值。

atanh 函数计算参数的反双曲正切值。如果参数不在 [-1, +1] 范围内,将发生域错误。如果参数等于 -1 或 +1,可能会发生范围错误。

#include <math.h>
float coshf(float x); /* C99 */
float sinhf(float x); /* C99 */
float tanhf(float x); /* C99 */
double cosh(double x); 
double sinh(double x);
double tanh(double x);
long double coshl(long double x); /* C99 */
long double sinhl(long double x); /* C99 */
long double tanhl(long double x); /* C99 */
float acoshf(float x); /* C99 */
float asinhf(float x); /* C99 */
float atanhf(float x); /* C99 */
double acosh(double x); /* C99 */
double asinh(double x); /* C99 */
double atanh(double x); /* C99 */
long double acoshl(long double x); /* C99 */
long double asinhl(long double x); /* C99 */
long double atanhl(long double x); /* C99 */

指数和对数函数

expexp2expm1 函数

exp 函数计算 x 的以 e 为底的指数值(e^x)。如果 x 的绝对值太大,会发生范围错误。

exp2 函数计算 x 的以 2 为底的指数值(2^x)。如果 x 的绝对值太大,会发生范围错误。

expm1 函数计算 x 的以 e 为底的指数值减去 1(e^x - 1)。如果 x 的绝对值太大,会发生范围错误。

#include <math.h>
float expf(float x); /* C99 */
double exp(double x);
long double expl(long double x); /* C99 */
float exp2f(float x); /* C99 */
double exp2(double x); /* C99 */
long double exp2l(long double x); /* C99 */
float expm1f(float x); /* C99 */
double expm1(double x); /* C99 */
long double expm1l(long double x); /* C99 */

exp 函数计算 x 的自然指数值(e^x)。如果 x 的绝对值过大,将产生范围错误。

exp2 函数计算以 2 为底的指数值(2^x)。如果 x 的绝对值过大,将产生范围错误。

expm1 函数计算 x 的自然指数值减去 1(e^x - 1)。如果 x 的绝对值过大,将产生范围错误。

frexpldexpmodfscalbnscalbln 函数

这些函数在软件浮点仿真器中被广泛使用,但在其他情况下很少直接调用。

在计算机内部,每个浮点数由两个部分表示:

  • 尾数在 [1/2, 1) 范围内,或者等于零。
  • 指数是一个整数。

浮点数的值 v 可表示为: v=significand×2exponentv = \text{significand} \times 2^{\text{exponent}}

frexp 函数将浮点数拆分为尾数和指数。它将指数存储在 ex 指向的整数对象中,并返回尾数。换句话说,返回的值是给定浮点数的副本,但其指数被替换为 0。如果值为 0,则结果的两个部分均为零。

ldexp 函数将浮点数乘以 2 的某个整数次方,并返回结果。换句话说,它返回给定浮点数的副本,指数增加了 ex。如果指数过大,可能会发生范围错误。

modf 函数将值拆分为整数部分和小数部分,两者的符号与参数相同。它将整数部分存储在 *iptr 指向的对象中,并返回小数部分。*iptr 是一个浮点类型,而不是 int 类型,因为它可能存储类似 1 000 000 000 000 000 000 000 这样太大的整数,无法容纳在 int 中。

scalbnscalbln 函数计算 x × FLT_RADIX^nFLT_RADIX 是浮点数系统的基数;如果它是 2,则这两个函数与 ldexp 等效。

#include <math.h>
float frexpf(float value, int *ex); /* C99 */
double frexp(double value, int *ex);
long double frexpl(long double value, int *ex); /* C99 */
float ldexpf(float x, int ex); /* C99 */
double ldexp(double x, int ex);
long double ldexpl(long double x, int ex); /* C99 */
float modff(float value, float *iptr); /* C99 */
double modf(double value, double *iptr); 
long double modfl(long double value, long double *iptr); /* C99 */
float scalbnf(float x, int ex); /* C99 */
double scalbn(double x, int ex); /* C99 */
long double scalbnl(long double x, int ex); /* C99 */
float scalblnf(float x, long int ex); /* C99 */
double scalbln(double x, long int ex); /* C99 */
long double scalblnl(long double x, long int ex); /* C99 */

loglog2log1plog10 函数

log 函数计算给定参数的自然对数,并返回结果。如果参数为负数,则会发生域错误;如果参数为零,则可能会发生范围错误。

log1p 函数计算 1 + x 的自然对数,并返回结果。如果参数小于 -1,则会发生域错误;如果参数为 -1,则可能会发生范围错误。

log10 函数计算给定参数的常用对数(以 10 为底),并返回结果。如果参数为负数,则会发生域错误;如果参数为零,则可能会发生范围错误。

log2 函数计算给定参数的以 2 为底的对数,并返回结果。如果参数为负数,则会发生域错误;如果参数为零,则可能会发生范围错误。

#include <math.h>
float logf(float x); /* C99 */
double log(double x);
long double logl(long double x); /* C99 */
float log1pf(float x); /* C99 */
double log1p(double x); /* C99 */
long double log1pl(long double x); /* C99 */
float log10f(float x); /* C99 */
double log10(double x);
long double log10l(long double x); /* C99 */
float log2f(float x); /* C99 */
double log2(double x); /* C99 */
long double log2l(long double x); /* C99 */

ilogblogb 函数

ilogb 函数提取 x 的指数值,并作为一个有符号整数返回。如果 x 为零,则返回 FP_ILOGB0;如果 x 是无穷大,则返回 INT_MAX;如果 x 是非数值(NaN),则返回 FP_ILOGBNAN。否则,它相当于调用相应的 logb 函数,并将返回值强制转换为整数类型。若 x 为零,则可能发生范围错误。FP_ILOGB0FP_ILOGBNAN 是在 math.h 中定义的宏;INT_MAX 是在 limits.h 中定义的宏。

logb 函数提取 x 的指数值,并作为浮点数格式的有符号整数返回。如果 x 是亚正常数,它将被当作标准数处理;因此,对于正的有限 x,满足 1 ≤ x × FLT_RADIX - logb(x) < FLT_RADIX,其中 FLT_RADIX 是浮点数的基数,在 float.h 中定义。

#include <math.h>
int ilogbf(float x); /* C99 */
int ilogb(double x); /* C99 */
int ilogbl(long double x); /* C99 */
float logbf(float x); /* C99 */
double logb(double x); /* C99 */
long double logbl(long double x); /* C99 */

幂运算函数

pow 函数

pow 函数计算 xy 次幂,并返回结果。如果 x 为负且 y 不是整数,则会发生域错误。如果 x 为零且 y 小于或等于零,也会发生域错误。可能会发生范围错误。

#include <math.h>
float powf(float x, float y); /* C99 */
double pow(double x, double y);
long double powl(long double x, long double y); /* C99 */

sqrt 函数

sqrt 函数计算 x 的正平方根,并返回结果。如果参数为负数,则会发生域错误。

#include <math.h>
float sqrtf(float x); /* C99 */
double sqrt(double x);
long double sqrtl(long double x); /* C99 */

cbrt 函数

cbrt 函数计算 x 的立方根,并返回结果。

#include <math.h>
float cbrtf(float x); /* C99 */
double cbrt(double x); /* C99 */
long double cbrtl(long double x); /* C99 */

hypot 函数

hypot 函数计算 xy 的平方和的平方根,避免溢出或下溢,并返回结果。

#include <math.h>
float hypotf(float x, float y); /* C99 */
double hypot(double x, double y); /* C99 */
long double hypotl(long double x, long double y); /* C99 */

最近整数、绝对值和余数函数

ceil 和 floor 函数
ceil 函数计算不小于 x 的最小整数值并返回结果;floor 函数计算不大于 x 的最大整数值并返回结果。

#include <math.h>
float ceilf(float x); /* C99 */
double ceil(double x);
long double ceill(long double x); /* C99 */
float floorf(float x); /* C99 */
double floor(double x);
long double floorl(long double x); /* C99 */

fabs 函数
fabs 函数计算浮动点数 x 的绝对值并返回结果。

#include <math.h>
float fabsf(float x); /* C99 */
double fabs(double x);
long double fabsl(long double x); /* C99 */

fmod 函数
fmod 函数计算浮动点数 x/y 的余数并返回值 x - i * y,其中 i 是某个整数,使得如果 y 非零,结果与 x 同符号,并且其大小小于 y 的大小。如果 y 为零,是否发生域错误或 fmod 函数返回零是实现定义的。

#include <math.h>
float fmodf(float x, float y); /* C99 */
double fmod(double x, double y);
long double fmodl(long double x, long double y); /* C99 */

nearbyint, rint, lrint, 和 llrint 函数
nearbyint 函数将其参数舍入为浮动点格式的整数值,使用当前舍入方向且不会引发“不精确”的浮动点异常。

rint 函数与 nearbyint 函数类似,但如果结果与参数的值不同,则可以引发“不精确”浮动点异常。

lrintllrint 函数根据当前舍入方向将其参数舍入为最接近的整数值。如果结果超出了返回类型的值范围,结果是未定义的,如果参数的大小过大,可能会发生范围错误。

#include <math.h>
float nearbyintf(float x); /* C99 */
double nearbyint(double x); /* C99 */
long double nearbyintl(long double x); /* C99 */
float rintf(float x); /* C99 */
double rint(double x); /* C99 */
long double rintl(long double x); /* C99 */
long int lrintf(float x); /* C99 */
long int lrint(double x); /* C99 */
long int lrintl(long double x); /* C99 */
long long int llrintf(float x); /* C99 */
long long int llrint(double x); /* C99 */
long long int llrintl(long double x); /* C99 */

round, lround, 和 llround 函数
round 函数将参数舍入为最接近的整数值,舍入时对于半数情况会远离零,而不管当前舍入方向。

lroundllround 函数将参数舍入为最接近的整数值,同样对于半数情况会远离零,而不管当前舍入方向。如果结果超出了返回类型的值范围,结果是未定义的,如果参数的大小过大,可能会发生范围错误。

#include <math.h>
float roundf(float x); /* C99 */
double round(double x); /* C99 */
long double roundl(long double x); /* C99 */
long int lroundf(float x); /* C99 */
long int lround(double x); /* C99 */
long int lroundl(long double x); /* C99 */
long long int llroundf(float x); /* C99 */
long long int llround(double x); /* C99 */
long long int llroundl(long double x); /* C99 */

trunc 函数
trunc 函数将其参数舍入为浮动点格式的整数值,该整数值与参数最接近但其大小不超过参数的绝对值。

#include <math.h>
float truncf(float x); /* C99 */
double trunc(double x); /* C99 */
long double truncl(long double x); /* C99 */

remainder 函数
remainder 函数根据 IEC 60559 定义计算余数 x REM y。定义为“当 y ≠ 0 时,余数 r = x REM y 无论舍入模式如何,都通过数学减法公式 r = x - n * y 得出,其中 nx/y 的最接近整数值;每当 |n - x/y| = ½ 时,n 为偶数。因此,余数始终是精确的。如果 r = 0,其符号与 x 相同。”这一定义适用于所有实现。

#include <math.h>
float remainderf(float x, float y); /* C99 */
double remainder(double x, double y); /* C99 */
long double remainderl(long double x, long double y); /* C99 */

remquo 函数
remquo 函数返回与 remainder 函数相同的余数。在由 quo 指向的对象中,它存储一个值,其符号与 x/y 的符号相同,其大小在模 2n 下与 x/y 的整数商的大小同余,其中 n 是一个实现定义的整数,且 n ≥ 3

#include <math.h>
float remquof(float x, float y, int *quo); /* C99 */
double remquo(double x, double y, int *quo); /* C99 */
long double remquol(long double x, long double y, int *quo); /* C99 */

误差和伽马函数

erf 函数计算参数的误差函数:

2π∫0xe−t2dt\frac{2}{\sqrt{\pi}} \int_0^x e^{-t^2} dt

erfc 函数计算参数的补充误差函数(即 1 - erf(x))。如果参数太大,可能会发生范围错误。

lgamma 函数计算参数的伽马函数的绝对值的自然对数(即 loge|Γ(x)|)。如果参数是负整数或零,可能会发生范围错误。

tgamma 函数计算参数的伽马函数(即 Γ(x))。如果参数是负整数,或者当参数为零时结果无法表示,则会发生域错误。也可能会发生范围错误。

#include <math.h>
float erff(float x); /* C99 */
double erf(double x); /* C99 */
long double erfl(long double x); /* C99 */
float erfcf(float x); /* C99 */
double erfc(double x); /* C99 */
long double erfcl(long double x); /* C99 */
float lgammaf(float x); /* C99 */
double lgamma(double x); /* C99 */
long double lgammal(long double x); /* C99 */
float tgammaf(float x); /* C99 */
double tgamma(double x); /* C99 */
long double tgammal(long double x); /* C99 */
最后修改: 2025年01月12日 星期日 13:29