CC++ & Algorithm

二进制转十进制:按权展开,C++轻松计算

困难24
语言版本:C++Python
概述:把二进制每一位乘以对应的权重(2的幂),加起来就是十进制,代码用循环逐位处理。

二进制转十进制,其实就像数糖果:按权展开一步步来

你有没有想过,电脑里存储的所有数字、文字、图片,其实都是一串串的 01?这就是二进制。但人类平常使用的是十进制(0~9),所以当我们想看懂计算机里的数字时,就需要把二进制转换成十进制。比如,你在游戏里攒了 1101 个金币(二进制),实际是多少个?换算成十进制就是 13 个——是不是很神奇?本文就来教你用 C++ 轻松转换,顺便用生活中的例子帮你彻底搞懂“按权展开”这个核心方法。

1. 二进制长什么样?为什么需要转换?

  • 二进制:只有 01 两个数字,每一位代表“有”或“无”(就像开关的“开”和“关”)。
  • 十进制:有 0~9 共十个数字,我们平时数零花钱、算分数用的就是十进制。
  • 转换的意义:计算机只懂二进制,但我们需要用人能看懂的形式输出结果。比如,你写一个程序统计自己一周的零花钱(二进制存入),最后要显示成十进制数字。

生活中的例子:假设你有一组糖果,用二进制来分组。例如 101 表示:第一组(从右向左)有1颗,第二组有0颗,第三组有1颗。总共是多少颗?按权展开就是 1×2² + 0×2¹ + 1×2⁰ = 4 + 0 + 1 = 5 颗。所以二进制 101 就等于十进制 5

2. 按权展开法:从右向左,每一位乘以 2 的幂

核心思想:把二进制数从最右边(最低位)开始,第几位就乘以 2 的几次方(指数从0开始),然后把所有结果加起来。

例如二进制 1101(从右向左四位:第0位是1,第1位是0,第2位是1,第3位是1):

第3位:1 × 2³ = 1 × 8 = 8
第2位:1 × 2² = 1 × 4 = 4
第1位:0 × 2¹ = 0 × 2 = 0
第0位:1 × 2⁰ = 1 × 1 = 1
总和 = 8 + 4 + 0 + 1 = 13

口诀:从右往左,指数递增;1就加,0就跳过

3. C++ 实现:两种主流写法(附生活化解释)

方法一:从左到右,用 pow 函数(简单但有小坑)

我们先把二进制当作一个字符串(例如 "1101")。从左到右遍历,第 i 个字符对应的权值是 2^(长度-1-i)。比如长度为4,第0个字符(最左边)对应 2^(4-1-0)=2³=8

#include <iostream>
#include <string>
#include <cmath>   // 使用 pow 函数
using namespace std;

int binaryToDecimal(string binary) {
    int decimal = 0;                // 存储转换后的十进制结果
    int len = binary.length();      // 二进制字符串的长度
    for (int i = 0; i < len; i++) {
        // 从左到右,第 i 位对应的权重是 2^(len-1-i)
        if (binary[i] == '1') {
            decimal += pow(2, len - 1 - i);
        }
    }
    return decimal;
}

int main() {
    string bin;
    cout << "请输入一个二进制字符串(例如1101): ";
    cin >> bin;
    cout << "十进制: " << binaryToDecimal(bin) << endl;
    return 0;
}

注意pow(2, x) 返回的是 double 类型,当指数很大(比如超过 31)时,浮点数可能不精确,而且 pow 计算速度较慢。所以这种方法不推荐用于实际项目,但适合新手理解原理。

方法二:从右向左,用变量 weight 累乘(更安全、更常用)

这是最经典的写法:从字符串的最右边(最低位)开始,用一个变量 weight 表示当前位的权重,weight 从1开始(2⁰),每处理一位就乘以2(变成2¹、2²……)。

#include <iostream>
#include <string>
using namespace std;

int binaryToDecimal(string binary) {
    int decimal = 0;        // 存储十进制结果
    int weight = 1;         // 初始权重为 2^0 = 1
    // 从右向左遍历
    for (int i = binary.length() - 1; i >= 0; i--) {
        if (binary[i] == '1')       // 如果当前位是'1'
            decimal += weight;      // 加上当前权重
        weight *= 2;                // 权重翻倍:2^0 -> 2^1 -> 2^2 ...
    }
    return decimal;
}

int main() {
    string bin;
    cout << "请输入一个二进制字符串(例如1101): ";
    cin >> bin;
    cout << "十进制: " << binaryToDecimal(bin) << endl;
    return 0;
}

生活类比:想象你在数一堆糖果,糖果按2倍递增摆放:第一格放1颗,第二格放2颗,第三格放4颗,第四格放8颗……你从右边开始检查每个格子里是否有糖果(如果有就加上对应的数量),同时准备下一个格子(权重乘2)。这样一次过就数完了,非常高效。

4. 新手最容易犯的 3 个错误

  1. 忘记字符串中的字符是 '0' 和 '1',直接当数字处理。比如写成 if (binary[i] == 1) 会永远不成立,因为字符 '1' 的 ASCII 值是 49,不等于整数1。

    • 正确写法:if (binary[i] == '1') (注意单引号)。
  2. 循环方向搞反。比如从左向右但权重未正确调整:如果从左向右,必须用 pow(2, len-1-i),很多新手直接 pow(2, i) 导致结果错误(会把 1101 算成 1×1 + 1×2 + 0×4 + 1×8 = 11,这是错的)。

    • 正确:从右向左累加权重,权重每次乘2,最清晰。
  3. 权重初始化或更新位置错误。例如,在循环内先 weight *= 2 再加,会导致第一个位的权重变成2(而不是1)。或者在循环外忘记重置 weight 等。

5. 完整可运行的代码示例(包含两种方法,带注释)

下面给出一个完整的程序,包含两种转换方法,你可以直接复制到 IDE 中运行,输入 1101 验证输出 13

#include <iostream>
#include <string>
#include <cmath>   // 仅方法一需要
using namespace std;

// 方法一:从左到右,用pow(示意用,不推荐大数)
int binaryToDecimal_pow(string binary) {
    int decimal = 0;                // 十进制结果
    int len = binary.length();      // 二进制字符串长度
    for (int i = 0; i < len; i++) {
        if (binary[i] == '1') {
            decimal += pow(2, len - 1 - i);  // 第i位权重 = 2^(长度-1-i)
        }
    }
    return decimal;
}

// 方法二:从右向左,用weight累乘(推荐!)
int binaryToDecimal(string binary) {
    int decimal = 0;        // 十进制结果
    int weight = 1;         // 当前权重,从2^0=1开始
    // 从字符串最右边(最低位)向左遍历
    for (int i = binary.length() - 1; i >= 0; i--) {
        if (binary[i] == '1') {
            decimal += weight;   // 如果该位是1,就加上当前权重
        }
        weight *= 2;             // 权重翻倍,准备下一位
    }
    return decimal;
}

int main() {
    string bin;
    cout << "请输入一个二进制字符串(只包含0和1,例如1101): ";
    cin >> bin;

    // 用方法二转换
    int result = binaryToDecimal(bin);
    cout << "转换结果(方法二,推荐): " << result << endl;

    // 也可以使用方法一(但注意pow的精度问题)
    // cout << "转换结果(方法一): " << binaryToDecimal_pow(bin) << endl;

    return 0;
}

运行示例

请输入一个二进制字符串(只包含0和1,例如1101): 1101
转换结果(方法二,推荐): 13

6. 相关知识点指引

  • 十转二:反过来,把十进制一直除以2,取余数(逆序排列)。这是“短除法”,可以练习把13转回1101。
  • 其他进制:八进制(权重是8的幂)、十六进制(权重是16的幂)。方法完全一样,只是基数不同。
  • 位运算:C++中的 <<(左移)相当于乘以2,>> 相当于除以2。用位运算实现二进制转十进制会更高效(例如 decimal = (decimal << 1) + (binary[i]-'0')),感兴趣的同学可以研究一下。
  • 字符串处理:熟悉 length()[] 下标操作,以及 string 类型的其他函数。

二进制转十进制是编程中基础又重要的技能。下次你在游戏里看到一个 101010 这样的代码,就能立刻算出它是多少了——而且你可以自己写个程序帮忙算!试试把上面代码跑起来,输入更多二进制看看结果对不对吧。

例题精讲

1单选题

二进制数110110转换为十进制的结果是?

A54
B52
C56
D50
2单选题

对于二进制数101,其最高位(最左边)的权重是2的多少次方?

A2⁰
B
C
D
3判断题

二进制数10010转换为十进制的结果是18。

4填空题
以下C++函数将二进制字符串(如"1011")转换为十进制整数。请补全循环开始时的指数初始值。\nint binToDec(string bin) {\n  int dec = 0;\n  int len = bin.length();\n  int exp = ___;\n  for (int i = 0; i < len; i++) {\n    if (bin[i] == '1') {\n      dec += pow(2, exp);\n    }\n    exp--;\n  }\n  return dec;\n}
5填空题
以下C++函数采用从低位到高位的方式将二进制字符串转换为十进制整数。请补全循环中权重的更新语句。\nint binToDec(string bin) {\n  int dec = 0;\n  int base = 1;\n  for (int i = bin.length()-1; i >= 0; i--) {\n    if (bin[i] == '1') {\n      dec += base;\n    }\n    ___;\n  }\n  return dec;\n}