中级 · 位与数组
二进制表示
把正整数打印成二进制:5 → 101。不许用字符串 — 优雅的路是 % 2 弹位、存进数组、倒着打印。
一句话答案用 n % 2 把二进制位一位位剥进数组,再倒着打印 —— 剥出来的顺序是低位在前,所以倒序这一步不能省。
题目
输入: 一个正整数 N(1 ≤ N ≤ 1023)。
输出: N 的二进制表示,无前导零。
样例:
| 输入 | 输出 |
|---|---|
5 | 101 |
8 | 1000 |
你的解答
「运行我的输入」用的自定义输入
判题在浏览器本地运行。死循环会在 3 秒后被自动中断 —— 但还是确保每个循环都有出口。代码随打随存。
卡住了?提示
提示 1 — 二进制就是换了个底数的拆位
你拆十进制用 % 10 和 / 10(数字之和)。二进制拆位用 % 2 和 / 2:5 → 1,2 → 0,1 → 1,然后到 0 停。弹出顺序:101 倒过来还是它自己 — 但试试 8。
提示 2 — 为什么 8 会坏掉
8 弹出来是 0, 0, 0, 1 — 低位在前。直接打印得到 0001;答案是 1000。所以把每一位存进数组(bits[k++] = n % 2;),再从 k-1 往 0 倒着打。N ≤ 1023 只要 ~10 个格子(10 位)。
题解(先自己试试!)
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
int bits[16];
int k = 0;
while (n > 0) {
bits[k++] = n % 2;
n /= 2;
}
for (int i = k - 1; i >= 0; i--) {
cout << bits[i];
}
cout << endl;
return 0;
}
"先暂存再倒着打"正是反转数字的概念版 — 数组只是把反转显式化了。在真编译器上,同样的活一行搞定:cout << bitset<8>(n);。进阶目标:八进制(改两个字符)或 10 以内的任意进制。
深度解析
为什么这样做对
跟十进制完全一样的剥位循环,只把基数从 10 换成 2。这就证明了:进制转换是一个带参数的算法,不是一堆算法。
代价
O(log₂ n),int 最多 32 轮。
常见错法
- 一边取位一边打印,输出是低位在前的。必须先收集、再倒着打印。
- C++ 里负数
n % 2得到负数。用 unsigned 或者先取 abs。
下一步
把刚取出来的位数一数:数一数 1 的个数。
记住这两句
- 进制转换 = 一个循环 + 一个基数参数。
- 取位是从低位开始的,必须倒序输出。
🐞 这段是错的 —— 点开,亲手让它挂一次
从低位往高位正着打印,顺序反了
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
while (n > 0) {
cout << n % 2;
n /= 2;
}
cout << endl;
return 0;
}