02|兩數相加
相關主題: C 基礎速查、資料型態與範圍、C 與 C++ 的關係
這題在練什麼
Section titled “這題在練什麼”整數的範圍。 兩個數字各自都在 int 的範圍內(最大約 21 億),但相加之後可能超過。題目的範例 2000000000 2000000000 就是在測這件事:答案 4000000000 已經超過 int 的上限 2147483647。
我的解法思路
Section titled “我的解法思路”直接把 a、b 宣告成 long long,讀取和輸出都用 %lld:
long long a, b;scanf("%lld %lld", &a, &b);printf("%lld\n", a + b);兩個數字本來就是 long long,加法也用 long long 計算,最大可以到 9.2 × 10^18,不會溢位。
- 只把結果宣告成
long long不夠:寫成int a, b; long long s = a + b;時,a + b會先用int算完,已經溢位了才存進s。這是未定義行為,不同的編譯選項會得到不同的結果,詳見資料型態與範圍的溢位範例。 - 格式要對:
long long用 scanf 讀取要寫%lld。寫成%d只會填 4 個 bytes,剩下的 4 個 bytes 是垃圾值。 - 用
int寫的話,沙盒會抓到:檢查的第一階段(UBSan)會報signed integer overflow,並指出是哪一行。
(還沒寫)
#include<stdio.h>int main() { long long a, b; scanf("%lld %lld", &a, &b); printf("%lld\n", a + b); return 0;}C 或 C++ 皆可|CPU 時間上限 1 秒
輸入兩個整數 a 和 b,輸出它們的和 a + b。
看起來很簡單,但請注意數字的範圍:答案可能會超過 int 存得下的範圍。
一行,兩個整數 a 和 b,中間用一個空白隔開。
- -2,000,000,000 ≤ a ≤ 2,000,000,000
- -2,000,000,000 ≤ b ≤ 2,000,000,000
一行,一個整數:a + b 的值。
輸入:
-7 12輸出:
5輸入:
2000000000 2000000000輸出:
4000000000int通常是 32 位元,範圍是 -2,147,483,648 到 2,147,483,647(大約正負 21 億)- 計算結果超出型別的範圍叫做「溢位」(overflow)。有號整數溢位在 C/C++ 是未定義行為,結果不可預期
long long至少 64 位元,範圍大約正負 9.2 × 10^18- C:
long long要用scanf("%lld", &x)讀、printf("%lld", x)印 - C++:
std::cin >>和std::cout <<會依照變數的型別自動處理,只要把變數宣告成long long
提示 1:為什麼用 int 會錯?
a 和 b 本身都放得進 int(最大約 21 億),但 2,000,000,000 + 2,000,000,000 = 4,000,000,000,超過了 int 的上限 2,147,483,647。
檢查時第一階段會開啟 Sanitizer,它會在溢位發生的那一行報告 signed integer overflow。
提示 2:寫了 long long sum = a + b; 為什麼還是錯?
如果 a 和 b 宣告成 int,a + b 會先用 int 算完(這時已經溢位了),之後才把結果轉成 long long 存進 sum,太晚了。
要讓計算本身就用 long long 進行:把 a 和 b 直接宣告成 long long,或寫成 (long long)a + b。
提示 3:C 的格式字串要跟著改
變數改成 long long 之後,scanf 和 printf 裡的 %d 都要改成 %lld。格式字串和型別不合是常見的 bug,編譯器通常會給警告(warning),記得看一下。