C 語言提供多種取整途徑,適用場景、精度、性能各異。本文系統歸納標準庫函數、整數運算技巧、自定義函數三大類方法,對比行為差異,給出選型建議與避坑指南。
| 函數 | 頭文件 | 行為 | 返回類型 | 示例 |
|---|---|---|---|---|
floor(x) | math.h | 向負無窮取整(向下) | double | floor(3.7)=3, floor(-3.7)=-4 |
ceil(x) | math.h | 向正無窮取整(向上) | double | ceil(3.2)=4, ceil(-3.2)=-3 |
trunc(x) | math.h (C99) | 向零取整(截斷小數) | double | trunc(3.7)=3, trunc(-3.7)=-3 |
round(x) | math.h (C99) | 四捨五入,半路情況遠離零 | double | round(3.5)=4, round(-3.5)=-4 |
lround(x) | math.h (C99) | round 並轉 long | long | 同上 |
rint(x) | math.h (C99) | 按當前舍入模式取整(默認銀行家算法) | double | rint(3.5)=4, rint(2.5)=2 (偶數) |
nearbyint(x) | math.h (C99) | 同 rint,但不觸發 FE_INEXACT異常 | double | 同上 |
編譯鏈接:GCC/Clang 需加 -lm 鏈接數學庫。
int i = (int)3.7; // 3 int j = (int)-3.7; // -3 // 直接賦值/強轉即為截斷,C 標準保證向零取整。
// 正數:整除自帶向下
int q = 7 / 3; // 2
// 負數:C 標準整除向零,需修正
int floor_div(int a, int b) { // b > 0
int q = a / b;
int r = a % b;
if (r != 0 && ((r > 0) != (b > 0))) q--; // 余數與除數異號,向下修正
return q;
}
// 通用公式:ceil(a/b) = (a + b - 1) / b (a≥0, b>0)
int ceil_div_pos(int a, int b) { return (a + b - 1) / b; }
// 通用有符號向上取整
int ceil_div(int a, int b) { // b > 0
int q = a / b;
int r = a % b;
if (r != 0 && ((r > 0) == (b > 0))) q++; // 余數與除數同號,向上修正
return q;
}
// 正數:(a + b/2) / b
int round_div_pos(int a, int b) { return (a + b/2) / b; }
// 通用:利用浮點 round 或手工判斷余數
int round_div(int a, int b) {
int q = a / b;
int r = a % b;
// 判斷 |r|*2 >= |b|
if (abs(r) * 2 >= abs(b)) q += (r > 0) == (b > 0) ? 1 : -1;
return q;
}
// 嵌入式常用:查表/多項式近似 exp/log,這裡給出簡易 floor/ceil
int my_floor(float x) {
int i = (int)x; // 截斷向零
if (x < 0 && x != i) i--; // 負數且有小數部分,向下修正
return i;
}
int my_ceil(float x) {
int i = (int)x;
if (x > 0 && x != i) i++; // 正數且有小數部分,向上修正
return i;
}
int my_round(float x) {
return (int)(x >= 0 ? x + 0.5f : x - 0.5f);
}
| 場景 | 推薦方法 | 理由 |
|---|---|---|
| 通用浮點計算、科學計算 | floor/ceil/round/rint | 標準、精確、可移植,鏈接 -lm |
| 嵌入式無 FPU、極致性能 | 整數除法技巧 (ceil_div 等) | 無浮點指令,僅整數 ALU,確定性週期 |
| 金融/統計需銀行家算法 | rint/nearbyint 或 bankers_div | 消除統計偏差,符合 IEEE 754/IEC 60559 |
| 圖形學/座標轉換 | floor/ceil 整數版 | 像素座標必為整數,向下/向上語義明確 |
| 網絡協議/分頁計算 | ceil_div_pos (a+b-1)/b | 正數通用,極簡高效 |
floor(100.0 * 0.29) 可能得 28(二進制無法精確表示 0.29)。金額計算必須用整數分/定點數。round(2.5) 得 3(遠離零),rint(2.5) 得 2(銀行家算法),業務含義不同。lround(1e18) 超出 long 範圍為未定義行為,需檢查範圍。math.h 函數返回 double,賦值給 float/int 會隱式轉換,可能丟失精度或溢出。C 語言取整工具箱豐富:標準庫函數覆蓋所有 IEEE 754 舍入模式,整數除法技巧為嵌入式/高性能場景提供零開銷方案,自定義函數適配無標準庫環境。選型核心:明確業務語義(向下/向上/四捨五入/銀行家)、確認數據範圍(正負/大小)、評估平台約束(FPU/標準庫/實時性)。