企業依據月利潤 I(萬元)分級提成發放獎金,規則如下:
| 利潤區間 | 提成比例 | 說明 |
|---|---|---|
| I ≤ 10 | 10% | 全額按 10% |
| 10 < I ≤ 20 | 7.5% | 超過 10 萬部分按 7.5% |
| 20 < I ≤ 40 | 5% | 超過 20 萬部分按 5% |
| 40 < I ≤ 60 | 3% | 超過 40 萬部分按 3% |
| 60 < I ≤ 100 | 1.5% | 超過 60 萬部分按 1.5% |
| I > 100 | 1% | 超過 100 萬部分按 1% |
預先計算各區間上界對應的累積獎金基數,主程式僅需判斷利潤落在哪個區間,再加上超出部分的獎金,避免重複乘加運算。
bonus1 = 10 * 0.10 = 1.00 // 10 萬以內
bonus2 = bonus1 + 10 * 0.075 = 1.75 // 20 萬以內
bonus4 = bonus2 + 20 * 0.05 = 2.75 // 40 萬以內
bonus6 = bonus4 + 20 * 0.03 = 3.35 // 60 萬以內
bonus10 = bonus6 + 40 * 0.015 = 3.95 // 100 萬以內
單位:萬元。主邏輯:
if (I <= 10) bonus = I * 0.10;
else if (I <= 20) bonus = bonus1 + (I - 10) * 0.075;
else if (I <= 40) bonus = bonus2 + (I - 20) * 0.05;
else if (I <= 60) bonus = bonus4 + (I - 40) * 0.03;
else if (I <= 100) bonus = bonus6 + (I - 60) * 0.015;
else bonus = bonus10 + (I - 100) * 0.01;
#include <stdio.h>
#include <stdlib.h>
int main(void) {
long profit; // 萬元單位
double bonus; // 獎金可能含小數
printf("請輸入當月利潤(萬元):");
if (scanf("%ld", &profit) != 1 || profit < 0) {
fprintf(stderr, "輸入錯誤:請輸入非負整數。\n");
return EXIT_FAILURE;
}
const double b1 = 10 * 0.10;
const double b2 = b1 + 10 * 0.075;
const double b4 = b2 + 20 * 0.05;
const double b6 = b4 + 20 * 0.03;
const double b10 = b6 + 40 * 0.015;
if (profit <= 10) bonus = profit * 0.10;
else if (profit <= 20) bonus = b1 + (profit - 10) * 0.075;
else if (profit <= 40) bonus = b2 + (profit - 20) * 0.05;
else if (profit <= 60) bonus = b4 + (profit - 40) * 0.03;
else if (profit <= 100) bonus = b6 + (profit - 60) * 0.015;
else bonus = b10 + (profit - 100) * 0.01;
printf("應發放獎金總額:%.2f 萬元\n", bonus);
return EXIT_SUCCESS;
}
long 避免 32 位元 int 溢位;獎金用 double 保留小數精度。scanf 回傳值與非負條件,增強健壯性。const double,編譯器可優化且防止誤改。%.2f 固定兩位小數,符合財務習慣。若稅制頻繁調整,建議改用結構體陣列:
typedef struct {
long threshold; // 區間上限(萬),最後一區間設 LONG_MAX
double rate; // 該區間稅率
double base; // 該區間起始累積獎金
} Bracket;
Bracket brackets[] = {
{10, 0.10, 0},
{20, 0.075, 1.0},
{40, 0.05, 1.75},
{60, 0.03, 2.75},
{100, 0.015, 3.35},
{LONG_MAX, 0.01, 3.95}
};
double calc_bonus(long profit) {
for (size_t i = 0; i < sizeof(brackets)/sizeof(brackets[0]); ++i) {
if (profit <= brackets[i].threshold)
return brackets[i].base + (profit - (i?brackets[i-1].threshold:0)) * brackets[i].rate;
}
return 0; // unreachable
}
新增/修改區間只需調整陣列資料,主邏輯完全不動,符合開放封閉原則。
| 輸入利潤(萬) | 預期獎金(萬) | 驗算說明 |
|---|---|---|
| 5 | 0.50 | 5×0.10 |
| 15 | 1.375 | 1.0 + 5×0.075 |
| 30 | 2.25 | 1.75 + 10×0.05 |
| 55 | 3.05 | 2.75 + 15×0.03 |
| 80 | 3.65 | 3.35 + 20×0.015 |
| 150 | 4.45 | 3.95 + 50×0.01 |
100000*0.1 中 0.1 為 double,但若寫成 1/10 會變整數除法得 0。務必使用浮點字面常數 0.1 或 1.0/10。else if 確保互斥完備,邊界值(10,20,40...)歸屬下一區間,符合「超過部分」語意。bonus,但加上 double bonus = 0; 更保險。本程式展示了分段函數建模、預計算優化、輸入驗證與資料驅動重構等實務技巧。從單一 main 邏輯出發,逐步演進為可維護、可擴充的結構,是從「寫出能跑的碼」邁向「工程化思維」的典型範例。