跳转到内容

C 编程/高等数学

来自 Wikibooks,开放世界中的开放书籍
上一页: 字符串 C 编程 下一页: 库

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

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

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

三角函数

[编辑 | 编辑源代码]

acos 和 asin 函数

[编辑 | 编辑源代码]

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 */

atan 和 atan2 函数

[编辑 | 编辑源代码]

atan 函数返回其参数的反正切值(以弧度为单位),atan2 函数返回 y/x 的反正切值(以弧度为单位)。atan 函数返回 [-π/2,+π/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 */

cos、sin 和 tan 函数

[编辑 | 编辑源代码]

cos、sin 和 tan 函数分别返回参数的余弦、正弦和正切值,以弧度表示。

 #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 */

双曲函数

[编辑 | 编辑源代码]

cosh, sinhtanh函数分别计算参数的双曲余弦、双曲正弦和双曲正切。对于双曲正弦和余弦函数,如果参数的大小太大,则会发生范围错误。

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 */

指数和对数函数

[编辑 | 编辑源代码]

exp、exp2 和 expm1 函数

[编辑 | 编辑源代码]

exp 函数计算 x 的以 e 为底的指数函数 (ex)。如果 x 的大小太大,则会发生范围错误。

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

expm1 函数计算参数的以 e 为底的指数函数,减去 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 */

frexp、ldexp、modf、scalbn 和 scalbln 函数

[编辑 | 编辑源代码]

这些函数在软件浮点模拟器中被大量使用,但在其他情况下很少被直接调用。

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

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

浮点数 的值是 .

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

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

modf 函数将参数 value 分解为整数部分和小数部分,它们都与参数具有相同的符号。它们将整数部分存储在 *iptr 指向的对象中,并返回小数部分。*iptr 是浮点类型,而不是 "int" 类型,因为它可能用于存储像 1 000 000 000 000 000 000 000 这样的整数,而这个整数太大,无法放入 int 中。

scalbnscalbln 计算 x × FLT_RADIXnFLT_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 */

大多数 C 浮点库还实现了 IEEE754 推荐的 nextafter()、nextUp() 和 nextDown() 函数。 [3]

loglog2log1plog10 函数

[edit | edit source]

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

log1p 函数计算参数加 1 的以 e 为底的自然对数,并返回结果。如果参数小于 -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 函数

[edit | edit source]

ilogb 函数将 x 的指数提取为带符号的 int 值。如果 x 为零,则它们返回 FP_ILOGB0 值;如果 x 为无穷大,则它们返回 INT_MAX 值;如果 x 为 NaN,则它们返回 FP_ILOGBNAN 值;否则,它们等效于调用相应的 logb 函数并将返回的值强制转换为 int 类型。如果 x 为零,则可能会发生范围错误。FP_ILOGB0FP_ILOGBNAN 是在 math.h 中定义的宏;INT_MAX 是在 limits.h 中定义的宏。

logb 函数将 x 的指数提取为浮点格式的带符号整数。如果 x 为非规格化数,则将其视为规格化数;因此,对于正有限的 x,1 ≤ x × FLT_RADIX-logb(x) < FLT_RADIXFLT_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 */

幂函数

[edit | edit source]

pow 函数

[edit | edit source]

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 函数

[edit | edit source]

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

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

cbrt 函数

[edit | edit source]

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

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

hypot 函数

[edit | edit source]

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 */

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

[edit | edit source]

ceilfloor 函数

[edit | edit source]

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 函数

[edit | edit source]

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

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

fmod 函数

[edit | edit source]

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 */

nearbyintrintlrintllrint 函数

[编辑 | 编辑源代码]

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 */

roundlroundllround 函数

[编辑 | 编辑源代码]

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 - ny 定义,其中 n 是最接近 x/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 是大于或等于 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 函数计算实参 的误差函数。

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

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 */

参考资料

[编辑 | 编辑源代码]
  1. [1] 为什么必须在 C 中链接数学库?


上一页: 字符串 C 编程 下一页: 库
华夏公益教科书