C 程式設計/高等數學
<math.h> 標頭檔案包含處理數學的幾個函式的原型。在 1990 年的 ISO 標準中,只指定了函式的 double 版本;1999 年的版本添加了 float 和 long double 版本。要使用這些數學函式,您必須將程式與數學庫連結。對於一些編譯器(包括 GCC),您必須指定額外的引數 -lm[1][2]。
數學函式可能會產生兩種錯誤。域錯誤發生在函式引數無效時,例如,將負數作為引數傳遞給sqrt(平方根函式)。範圍錯誤發生在函式結果無法用特定浮點型別表示時,例如pow(1000.0, 1000.0)如果 double 的最大值約為 10308。
這些函式可以分為以下幾類
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 函式返回 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 函式分別返回引數的餘弦、正弦和正切值,以弧度表示。
#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, sinh和tanh函式分別計算引數的雙曲餘弦、雙曲正弦和雙曲正切。對於雙曲正弦和餘弦函式,如果引數的大小太大,則會發生範圍錯誤。
該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 函式計算 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 */
這些函式在軟體浮點模擬器中被大量使用,但在其他情況下很少被直接呼叫。
在計算機內部,每個浮點數都由兩個部分表示
- 尾數要麼在 [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 中。
scalbn 和 scalbln 計算 x × FLT_RADIXn。FLT_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]
log、log2、log1p 和 log10 函式
[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 */
ilogb 和 logb 函式
[edit | edit source]ilogb 函式將 x 的指數提取為帶符號的 int 值。如果 x 為零,則它們返回 FP_ILOGB0 值;如果 x 為無窮大,則它們返回 INT_MAX 值;如果 x 為 NaN,則它們返回 FP_ILOGBNAN 值;否則,它們等效於呼叫相應的 logb 函式並將返回的值強制轉換為 int 型別。如果 x 為零,則可能會發生範圍錯誤。FP_ILOGB0 和 FP_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 */
冪函式
[edit | edit source]pow 函式
[edit | edit source]pow 函式計算 x 的 y 次冪,並返回結果。如果 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 函式計算 x 和 y 的平方和的平方根,避免溢位或下溢,並返回結果。
#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]ceil 和 floor 函式
[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 */
nearbyint 函式將它們的實參四捨五入到浮點格式的整數值,使用當前的舍入方向,並且不會引發“不精確”浮點異常。
rint 函式類似於 nearbyint 函式,但如果結果與實參的值不同,它們可能會引發“不精確”浮點異常。
lrint 和 llrint 函式根據當前的舍入方向將它們的實參四捨五入到最接近的整數值。如果結果超出返回型別的值範圍,則數值結果未定義,如果實參的大小過大,則可能會發生範圍錯誤。
#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 函式將實參四捨五入到最接近的整數值,無論當前的舍入方向如何,都將半途而廢的情況四捨五入到遠離零的方向。如果結果超出返回型別的值範圍,則數值結果未定義,如果實參的大小過大,則可能會發生範圍錯誤。
#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 函式將它們的實參四捨五入到浮點格式的整數值,該整數值最接近實參,但大小不超過實參。
#include <math.h>
float truncf(float x); /* C99 */
double trunc(double x); /* C99 */
long double truncl(long double x); /* C99 */
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 函式返回與 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 */