「兩數求和」是所有編程語言的 Hello World 級練習。本文從最基礎的輸入輸出模板,延伸至加法交換律/結合律的數學本質、C 語言自增自減運算符前後綴陷阱、斷言驗證技術,構建扎實的數值計算認知體系。
#include <stdio.h>
int main() {
int a, b;
// 多組測試數據讀取直到 EOF
while (scanf("%d %d", &a, &b) == 2) {
printf("%d\n", a + b);
}
return 0;
}
工程化細節:
scanf 返回成功讀取的項數,== 2 確保兩個整數均讀取成功while 循環天然支持多組測試數據(OJ 常見要求)2000 9 → 輸出 2009,驗證大數加法無溢出(int 32 位足夠)| 律名 | 數學表達 | 程序驗證代碼片段 | 編程意義 |
|---|---|---|---|
| 交換律 | a + b = b + a | assert(a + b == b + a); | 運算順序不影響結果,優化編譯器可重排指令 |
| 結合律 | (a + b) + c = a + (b + c) | assert((a + b) + c == a + (b + c)); | 分組方式不影響結果,但浮點數因精度可能不成立! |
關鍵警示: 浮點數加法不滿足結合律(如 (1e20 + -1e20) + 1 = 1 但 1e20 + (-1e20 + 1) = 0),財務/科學計算必須用定點數或專用庫。
使用 assert 進行編碼期驗證(需 #include <assert.h>):
int main() {
int a;
// 前綴 ++a:先增後用
a = 5; assert(++a == 6); // a 變 6,表達式值 6
// 後綴 a++:先用後增
a = 5; assert(a++ == 5); // 表達式值 5,a 隨後變 6
assert(a == 6);
// 前綴 --a:先減後用
a = 5; assert(--a == 4);
// 後綴 a--:先用後減
a = 5; assert(a-- == 5);
assert(a == 4);
return 0;
}
int、long、short 等fmod()(math.h)或 remainder()(a/b)*b + a%b == a,商向零截斷,餘數符號同被除數C11 _Static_assert 編譯期檢查(不產生運行時代碼):
_Static_assert(sizeof(int) >= 4, "int must be at least 32 bits"); _Static_assert(INT_MAX >= 32767, "INT_MAX too small");
| 錯誤代碼 | 現象 | 原因 | 修正 |
|---|---|---|---|
scanf("%d", a) | 崩潰/輸出亂碼 | 缺少取地址符 & | scanf("%d", &a) |
printf("%d", a+b) | 格式化錯誤 | 缺少換行或格式符不匹配 | printf("%d\n", a+b) |
int c = a+++b; | 編譯歧義 | 解析為 (a++) + b | 加空格 a++ + b 或括號 |
| 浮點數直接 == 比較 | 邏輯錯誤 | 精度誤差 | 用 fabs(a-b) < EPS |
從簡單的 A+B 出發,觸類旁通至數學運算律、運算符優先級、斷言防禦性編程、浮點數陷阱,這正是「以簡馭繁」的編程內功心法。建議將斷言驗證納入日常編碼習慣,讓錯誤在編譯期或測試期暴露,而非生產環境。