1. 前言 math.h
是什麼? C 語言有支援數學計算的標準函式庫 math.h
。使用此函式庫即可執行三角函數、指數與對數計算、平方根、絕對值等各種數學運算。math.h
的使用好處可用簡單的函式實作數學計算 可輕鬆實作高精度計算 作為標準函式庫,無需額外安裝 math.h
的引用方式 math.h
若要使用,請在程式開頭以如下方式寫入 #include
指令。#include <stdio.h>
#include <math.h>
此外,若使用 math.h
的函式,需在編譯時加入 -lm
選項 。例如,使用 GCC 時可如下編譯。gcc program.c -o program -lm
math.h
的主要用途 math.h
可用於以下用途。利用三角函數進行角度計算 利用指數與對數進行數值運算 平方根計算 數值的四捨五入處理 絕對值計算
2. 用途別 math.h
的主要函式 2.1 三角函式(角度的計算) 三角函式用於圓形與三角形的計算,並在物理模擬、圖形處理等廣泛領域中活用。sin()
、cos()
、tan()
的概述 這些函式分別用於求取 正弦(sine)、餘弦(cosine)、正切(tangent) 。#include <stdio.h>
#include <math.h>
int main() {
double angle = 3.14159 / 4; // 45度(弧度)
printf("sin(45°) = %f
", sin(angle));
printf("cos(45°) = %f
", cos(angle));
printf("tan(45°) = %f
", tan(angle));
return 0;
}
執行結果 sin(45°) = 0.707107
cos(45°) = 0.707107
tan(45°) = 1.000000
注意事項 math.h
的三角函式以 弧度 為輸入。度單位的值使用時,需要 (角度 × π / 180)
的轉換。double degrees = 45.0;
double radians = degrees * M_PI / 180.0;
2.2 反三角函式(求取角度) 反三角函式用於從給定的比例求取角度。asin()
、acos()
、atan()
、atan2()
的概述asin(x)
:返回 x 的反正弦(arc sine),範圍為(-π/2 ~ π/2)acos(x)
:返回 x 的反餘弦(arc cosine),範圍為(0 ~ π)atan(x)
:返回 x 的反正切(arc tangent),範圍為(-π/2 ~ π/2)atan2(y, x)
:返回 y/x
的反正切(支援全部象限)#include <stdio.h>
#include <math.h>
int main() {
double value = 0.5;
printf("asin(0.5) = %f 弧度
", asin(value));
printf("acos(0.5) = %f 弧度
", acos(value));
printf("atan(1.0) = %f 弧度
", atan(1.0));
printf("atan2(1.0, 1.0) = %f 弧度
", atan2(1.0, 1.0));
return 0;
}
注意事項 asin()
與 acos()
的參數必須在 -1.0
到 1.0
之間。超出此範圍會返回 NaN
(非數)。2.3 指數與對數函式(指數計算與對數計算) 指數與對數的計算廣泛用於資料分析、統計、機器學習等。exp()
、log()
、log10()
的概述exp(x)
:計算 e^xlog(x)
:計算自然對數(ln x),底為 elog10(x)
:計算常用對數(底 10)#include <stdio.h>
#include <math.h>
int main() {
double x = 2.0;
printf("exp(2.0) = %f
", exp(x));
printf("log(10.0) = %f
", log(10.0));
printf("log10(100.0) = %f
", log10(100.0));
return 0;
}
執行結果 exp(2.0) = 7.389056
log(10.0) = 2.302585
log10(100.0) = 2.000000
注意事項 log()
若傳入 ≤0 的值會返回 NaN
(例如:log(0.0)
)。exp(x)
若傳入過大值可能會 溢位 。2.4 次方與平方根(數值運算) 次方與平方根的計算是許多數學演算法的基本處理。pow()
、sqrt()
的概述pow(x, y)
:計算 x^y
(x 的 y 次方)sqrt(x)
:計算 x
的平方根#include <stdio.h>
#include <math.h>
int main() {
double x = 9.0;
printf("pow(2, 3) = %f
", pow(2.0, 3.0));
printf("sqrt(9.0) = %f
", sqrt(x));
return 0;
}
注意事項 pow(x, y)
若將 y 指定為 0.5
也可計算平方根(pow(9.0, 0.5) = 3.0
)。sqrt(x)
若傳入負值會返回 NaN
。2.5 數值處理(四捨五入與絕對值) 數值四捨五入為整數或求取絕對值的函式,在金額計算與整數處理上很重要。fabs()
、ceil()
、floor()
、round()
的概述fabs(x)
:求取 x 的絕對值ceil(x)
:將 x 向上取整(小數點以下進位)floor(x)
:將 x 向下取整(小數點以下捨去)round(x)
:將 x 四捨五入#include <stdio.h>
#include <math.h>
int main() {
double num = -5.7;
printf("fabs(-5.7) = %f
", fabs(num));
printf("ceil(-5.7) = %f
", ceil(num));
printf("floor(-5.7) = %f
", floor(num));
printf("round(-5.7) = %f
", round(num));
return 0;
}
執行結果 fabs(-5.7) = 5.700000
ceil(-5.7) = -5.000000
floor(-5.7) = -6.000000
round(-5.7) = -6.000000
3. math.h
的使用方法與注意事項 3.1 使用 math.h
時的編譯選項 使用 math.h
時,許多 C 編譯器需要 明確鏈接數學函式庫(libm
) 。GCC 的編譯方式 使用 GCC 時,如果未指定 -lm
選項,包含數學函式的程式將無法正確鏈接,可能會出現以下錯誤。undefined reference to `sin'
為避免此問題,請如以下方式加入 -lm
選項進行編譯。gcc program.c -o program -lm
Clang 與 MSVC 的情況 在某些環境下,Clang 仍可能需要 -lm
選項。 在 Microsoft Visual Studio(MSVC)中,即使未指定 -lm
,也能使用 math.h
的函式。 3.2 浮點數精度與誤差的注意事項 math.h
中的數學函式使用 浮點運算(IEEE 754 標準) ,因此可能會產生精度誤差。什麼是浮點誤差? 浮點數在內部以 近似值 表示,無法保持精確值。因此,計算結果可能會產生微小誤差。誤差的具體例子 #include <stdio.h>
#include <math.h>
int main() {
double x = 0.1;
double y = 0.2;
double z = 0.3;
if ((x + y) == z) {
printf("Equaln");
} else {
printf("Not Equaln");
}
return 0;
}
輸出 Not Equal
如此,會出現 0.1 + 0.2
無法嚴格等於 0.3
的情況。考慮浮點誤差的比較 在考慮誤差時,會設定 閾值(epsilon) 來進行比較。#include <stdio.h>
#include <math.h>
#define EPSILON 1e-9
int main() {
double x = 0.1, y = 0.2, z = 0.3;
if (fabs((x + y) - z) < EPSILON) {
printf("Approximately Equaln");
} else {
printf("Not Equaln");
}
return 0;
}
輸出 Approximately Equal
3.3 math.h
的錯誤處理 math.h
的函式中,有些在傳入 無效參數 時會產生錯誤。此時需要適當處理錯誤。錯誤發生的例子 sqrt(-1.0)
→ NaN
(非數)log(0.0)
→ -inf
(負無限大)1.0 / 0.0
→ inf
(正無限大)使用 errno
的錯誤處理 #include <stdio.h>
#include <math.h>
#include <errno.h>
int main() {
errno = 0; // 重設 errno
double result = sqrt(-1.0);
if (errno != 0) {
perror("計算錯誤發生");
} else {
printf("結果: %fn", result);
}
return 0;
}
errno
的主要錯誤代碼錯誤代碼 意義 EDOM
數學函式傳入無效值(例如: sqrt(-1.0)
) ERANGE
結果超出可表示的範圍(例如: exp(1000.0)
)
3.4 math.h
使用的最佳實踐 編譯時加入 -lm
選項 考慮浮點誤差,比較時使用閾值 對於傳入的無效輸入值進行錯誤處理 檢查避免發生溢位/下溢 確認計算結果不是 NaN
或 inf
4. FAQ(常見問題) 4.1 math.h
的函式發生錯誤時的處理方法? 問題範例 #include <stdio.h>
#include <math.h>
int main() {
double result = sqrt(-1.0);
printf("sqrt(-1.0) = %fn", result);
return 0;
}
輸出 sqrt(-1.0) = nan
這樣,當求負數的平方根時,會返回 NaN
(Not a Number)。對策 事先檢查輸入值 ,避免無效的值進入。利用 errno
來偵測錯誤 。#include <stdio.h>
#include <math.h>
#include <errno.h>
int main() {
errno = 0;
double result = sqrt(-1.0);
if (errno == EDOM) {
printf("錯誤: 無效的輸入值n");
} else {
printf("sqrt(-1.0) = %fn", result);
}
return 0;
}
4.2 使用 math.h
時需要的編譯選項是什麼? C 語言的 math.h
依賴於 數學函式庫(libm) 。
因此,在使用 GCC 編譯時,需要加入 -lm
選項 。編譯方法 gcc program.c -o program -lm
如果不指定選項會怎樣? GCC 若未加 -lm
而使用 math.h
的函式,會出現以下 「undefined reference」錯誤 。/tmp/ccxlj3hs.o: In function `main':
program.c:(.text+0x15): undefined reference to `sin'
collect2: error: ld returned 1 exit status
4.3 使用 math.h
的函式時的精度如何? math.h
使用基於 IEEE 754 標準 的浮點數,運算精度有限。問題範例 #include <stdio.h>
#include <math.h>
int main() {
double x = 0.1, y = 0.2;
double z = x + y;
if (z == 0.3) {
printf("等於n");
} else {
printf("不同n");
}
return 0;
}
輸出 不同
對策 浮點數比較時需要 考慮誤差容忍範圍(EPSILON) 。#include <stdio.h>
#include <math.h>
#define EPSILON 1e-9
int main() {
double x = 0.1, y = 0.2, z = 0.3;
if (fabs((x + y) - z) < EPSILON) {
printf("幾乎相等n");
} else {
printf("不同n");
}
return 0;
}
輸出 幾乎相等
4.4 math.h
的函式可以用於整數型嗎? math.h
的函式假設以浮點型(double
)作為參數。
因此,傳入整數時會 隱式轉換為 double
。問題範例 #include <stdio.h>
#include <math.h>
int main() {
int x = 4;
printf("sqrt(4) = %fn", sqrt(x));
return 0;
}
對策 透過明確的型別轉換,可防止意外的行為。#include <stdio.h>
#include <math.h>
int main() {
int x = 4;
double result = sqrt((double)x); // 明確的型別轉換
printf("sqrt(4) = %fn", result);
return 0;
}
4.5 math.h
中有定義圓周率常數嗎? C99 之後的標準在 math.h
中定義了圓周率(π)的常數 M_PI
。使用範例 #include <stdio.h>
#include <math.h>
int main() {
printf("π = %.15fn", M_PI);
return 0;
}
輸出 π = 3.141592653589793
如果無法使用 M_PI
在某些編譯器或舊環境中,M_PI
可能未被定義。此時需要 自行定義 。#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
5. math.h
的應用:實用範例 5.1 物理模擬中的應用 1. 物體的落下運動(自由落下的計算) #include <stdio.h>
#include <math.h>
#define G 9.81 // 重力加速度
int main() {
double time = 3.0; // 3秒的落下
double distance = 0.5 * G * pow(time, 2);
printf("物體在 %.2f 秒後會落下 %.2f 公尺。n", time, distance);
return 0;
}
輸出 物體在 3.00 秒後會落下 44.15 公尺。
5.2 統計分析中的應用 標準差的計算 #include <stdio.h>
#include <math.h>
double mean(double data[], int size) {
double sum = 0.0;
for (int i = 0; i < size; i++) {
sum += data[i];
}
return sum / size;
}
double standardDeviation(double data[], int size) {
double avg = mean(data, size);
double sum = 0.0;
for (int i = 0; i < size; i++) {
sum += pow(data[i] - avg, 2);
}
return sqrt(sum / size);
}
int main() {
double dataset[] = {10.0, 20.0, 30.0, 40.0, 50.0};
int size = sizeof(dataset) / sizeof(dataset[0]);
printf("標準差: %.2fn", standardDeviation(dataset, size));
return 0;
}
輸出 標準差: 14.14
5.3 遊戲開發中的應用 2D 遊戲中的角色角度計算 #include <stdio.h>
#include <math.h>
int main() {
double playerX = 1.0, playerY = 1.0;
double enemyX = 4.0, enemyY = 5.0;
double angle = atan2(enemyY - playerY, enemyX - playerX) * 180.0 / M_PI;
printf("敵人的方向: %.2f 度n", angle);
return 0;
}
輸出 敵人的方向: 45.00 度
3D 遊戲中的碰撞判定 #include <stdio.h>
#include <math.h>
int main() {
double obj1[3] = {1.0, 2.0, 3.0}; // 物件1的座標
double obj2[3] = {4.0, 6.0, 3.0}; // 物件2的座標
double distance;
distance = sqrt(pow(obj2[0] - obj1[0], 2) +
pow(obj2[1] - obj1[1], 2) +
pow(obj2[2] - obj1[2], 2));
printf("物件間的距離: %.2fn", distance);
return 0;
}
輸出 物件間的距離: 5.00
6. 總結 6.1 math.h
的主要要點 math.h
的基礎C 語言的標準函式庫,用於數學計算。 #include <math.h>
需要在程式的開頭宣告。編譯時的注意事項 math.h
的函式若要使用,GCC 需要 -lm
選項。 gcc program.c -o program -lm
依用途的主要函式 三角函式(sin, cos, tan) → 角度計算反三角函式(asin, acos, atan, atan2) → 取得角度指數與對數(exp, log, log10) → 指數與對數運算冪次與平方根(pow, sqrt) → 冪次與平方根數值處理(fabs, ceil, floor, round) → 絕對值與四捨五入處理精度與誤差的考量 math.h
的函式使用 浮點運算(IEEE 754 標準) ,因此會產生精度誤差。 #define EPSILON 1e-9
if (fabs(a - b) < EPSILON) { /* 判斷為幾乎相等 */ }
錯誤處理 傳入無效的輸入(例如 sqrt(-1.0)
, log(0.0)
)可能會產生 NaN
或 inf
。 errno = 0;
double result = sqrt(-1.0);
if (errno != 0) {
perror("錯誤發生");
}
實用範例 物理模擬 → 計算落體運動與拋射運動統計分析 → 計算標準差遊戲開發 → 敵人方向計算(atan2()
)與碰撞判定(sqrt()
)6.2 math.h
學習參考連結 如果想更深入了解 math.h
,建議利用以下資源。6.3 最終學習步驟 嘗試基本函式 sqrt()
, pow()
, sin()
, cos()
等函式,製作簡單的程式。撰寫考慮錯誤處理的程式碼 製作實用程式 在遊戲開發、資料分析等具體專案中活用 math.h。
最終總結 math.h
作為 C 語言的標準函式庫,提供許多數學函式。了解正確的使用方式,並考慮精度誤差與錯誤處理,即可 更安全且精確地執行數學運算 。請在實際程式中活用 math.h
,挑戰更高階的 C 程式設計。