16.3 進制字串轉成整數
紙上會算了,換程式來。第一個方向:讀入一串 K 進制的數字,算出它的值。
輸入是一串「位」,用 string 讀(10.7)最自然;每個字元要先變回數值——這正是 8.2 的看家本領:數字字元用 c - '0',字母位則是「跟 'A' 的距離再加 10」:
int charToDigit(char c) {
if (c >= '0' && c <= '9') return c - '0';
return c - 'A' + 10; // 'A' 是 10、'B' 是 11……
}
這個函式假設字母是大寫。若題目給的是小寫 a ~ f,先用 8.5 的 toupper 統一再送進來——直接對小寫做 - 'A' + 10 會得到錯得離譜的值('a' - 'A' + 10 是 42,不是 10)。
¶方向一:由高位至低位(推薦)
想想你是怎麼「讀」出 3072 這個數的。逐字看到 3、0、7、2,心裡的數字其實是這樣長大的:3 \to 30 \to 307 \to 3072——每看到新的一位,手上的數整體乘 10,再把新數字放進個位。把 10 換成 K,就是進制轉換的核心式:
拿 (11010)_2 走一遍:
| 讀到的字元 | 運算 | val 變成 |
|---|---|---|
'1' |
0 \times 2 + 1 | 1 |
'1' |
1 \times 2 + 1 | 3 |
'0' |
3 \times 2 + 0 | 6 |
'1' |
6 \times 2 + 1 | 13 |
'0' |
13 \times 2 + 0 | 26 |
跟 16.1 手算的 26 一致。完整程式(輸入進制 K 與 K 進制字串,輸出十進制值):
#include <iostream>
#include <string>
using namespace std;
// 進制位字元 -> 數值:'0'~'9' 用 8.2 的減法,'A' 起跳的字母代表 10 以上
int charToDigit(char c) {
if (c >= '0' && c <= '9') return c - '0';
return c - 'A' + 10;
}
int main() {
int K;
string s;
cin >> K >> s; // K 進制的字串 s
long long val = 0; // 數值上看 10^18:用 long long
for (int i = 0; i < (int)s.size(); i++) {
val = val * K + charToDigit(s[i]); // 舊值整體升一位,個位放新數字
}
cout << val << '\n';
return 0;
}
執行結果(輸入 16 與 1A):
26
(1A)_{16} = 1 \times 16 + 10 = 26——換輸入 2 與 11010 跑跑看,同樣得到 26。注意 val 宣告成 long long:題目的數值動輒上看 10^{18},用 int 一路乘上去必溢位(上冊 2.9)。
¶方向二:由低位至高位
也可以照 16.1 手算的方式:從最右邊(低位)開始,每一位乘上自己的位值 K^i 再加總。位值用一個變數 mul 一路乘上去:
#include <iostream>
#include <string>
using namespace std;
int charToDigit(char c) {
if (c >= '0' && c <= '9') return c - '0';
return c - 'A' + 10;
}
int main() {
int K;
string s;
cin >> K >> s;
long long val = 0;
long long mul = 1; // mul = 目前這一位的位值 K^i
for (int i = (int)s.size() - 1; i >= 0; i--) {
val += mul * charToDigit(s[i]); // 這一位的貢獻:數字 × 位值
if (i > 0) mul *= K; // 位值升一級(最後一次不用,避免多乘一次爆範圍)
}
cout << val << '\n';
return 0;
}
輸出跟方向一完全相同。多解釋一下倒數第二行的 if (i > 0):最高位處理完後,mul 不會再被用到,但若放任它多乘最後一次 K,在數值貼近 long long 上限時(例如 19 位的十進制輸入),這次多餘的乘法自己就先溢位了(2.9)——一個 if 把隱患拆掉。
兩種方向都對,推薦方向一:不用管位值變數、迴圈順向好寫,而且它需要的「由高位往低位逐字掃」恰好就是字串本來的順序。
動手試試看:先手算 36 進制的 AA 是多少(A 是 10,所以是 10 \times 36 + 10 = 370),再拿本節任一版程式驗證;順便輸入 2 與你在 16.1 算過的 101101,看看是不是 45。