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 -lmmath.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.0000003. math.h 的使用方法與注意事項 3.1 使用 math.h 時的編譯選項 使用 math.h 時,許多 C 編譯器需要 明確鏈接數學函式庫(libm) 。GCC 的編譯方式 使用 GCC 時,如果未指定 -lm 選項,包含數學函式的程式將無法正確鏈接,可能會出現以下錯誤。undefined reference to `sin' 為避免此問題,請如以下方式加入 -lm 選項進行編譯。gcc program.c -o program -lmClang 與 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 Equal3.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 status4.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.145.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 程式設計。