中级 · 位与数组

二进制表示

把正整数打印成二进制:5 → 101。不许用字符串 — 优雅的路是 % 2 弹位、存进数组、倒着打印。

一句话答案用 n % 2 把二进制位一位位剥进数组,再倒着打印 —— 剥出来的顺序是低位在前,所以倒序这一步不能省。

题目

输入: 一个正整数 N(1 ≤ N ≤ 1023)。

输出: N 的二进制表示,无前导零。

样例:

输入输出
5101
81000

你的解答

main.cpp — 你的解答
「运行我的输入」用的自定义输入

判题在浏览器本地运行。死循环会在 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;
}