第十八天:C++进制之间的转换
C++进制之间的转换
一、进制
- 十进制
十进制是我们日常生活中最常用的数字表示方法,它使用0-9这十个基本数字符号来表示数值。在编程中,十进制数可以像我们平时书写数字一样直接使用,不需要任何特殊的前缀或符号。
举个例子,在C语言中声明一个十进制整数变量时:
int decimalNum = 10; // 这里的10就是标准的十进制表示
- 二进制
在C++17及之后的版本中,二进制数得到了更规范化的支持,新增了0b或0B前缀来表示二进制字面量。这个特性使得二进制数在代码中的表示更加直观和标准化,就像十六进制使用0x前缀一样自然。例如,我们可以这样声明一个二进制变量:int binaryNum = 0b1010;
,其中1010代表二进制的1010,相当于十进制的10。
二进制是计算机最基础的语言,每个二进制位(bit)都像是一个微小的开关,可以表示开(1)或关(0)的状态。计算机处理器就是通过这种简单的二元状态来执行所有复杂的计算和逻辑操作。比如:
- 0b0001 表示十进制的1
- 0b0010 表示十进制的2
- 0b0100 表示十进制的4
- 0b1000 表示十进制的8
这种表示方式在底层编程中特别有用,比如:
- 硬件寄存器操作(通过位掩码来设置或清除特定标志位)
- 网络协议中的标志位处理
- 嵌入式系统中直接与硬件交互
- 需要精确控制内存使用的场景
C++17引入这个特性后,程序员可以更清晰地表达自己的意图,避免了以往需要通过十六进制或十进制来间接表示二进制数的尴尬。例如,设置一个包含多个标志位的变量现在可以这样写:
constexpr int FLAG_A = 0b0001;
constexpr int FLAG_B = 0b0010;
constexpr int FLAG_C = 0b0100;
int settings = FLAG_A | FLAG_C; // 设置A和C标志
- 八进制
八进制是一种以8为基数的计数系统,在编程语言中通常以数字0作为前缀来表示,这种特殊的标记方式确实赋予了它一种神秘感。例如在C/C++或Java中声明int octalNum = 012;
时,这个看似普通的数字实际上表示八进制数值。
- 八进制数012可以分解为:
- 第一位1表示1×8^1=8
- 第二位2表示2×8^0=2
- 相加得到十进制值:8 + 2 = 10
八进制在计算机领域有着特定的应用场景:
-
UNIX/Linux系统中的文件权限设置就采用八进制表示法,如chmod 755命令
-
早期计算机系统(如PDP-8)采用12位和36位字长,正好对应3位和9位八进制数
-
某些嵌入式系统和硬件设备的寄存器配置会使用八进制编码
-
十六进制
十六进制数值以 0x 或 0X 作为前缀标识,这是大多数编程语言(如C/C++、Java、Python等)遵循的通用规范。例如在代码 int hexadecimalNum = 0xA; 中,0x 明确表示后续的 A 是一个十六进制数字,其中 A 对应的十进制值为 10,B 为11,依此类推到 F 表示15。
十六进制表示法在计算机领域有着诸多重要应用:
- 内存寻址:操作系统和底层程序常用十六进制表示内存地址,如0x00007FF6AC3A4DF0
- 色彩编码:网页设计中十六进制表示RGB颜色值,如纯红色表示为0xFF0000
- 二进制数据转储:调试时常用十六进制显示二进制数据
- 硬件寄存器:嵌入式开发中寄存器配置常用十六进制值
这种表示法的优势在于:
- 与二进制转换方便(每个十六进制位对应4个二进制位)
- 比二进制更紧凑易读
- 避免了十进制与二进制转换的复杂性。
二、十进制转换其他进制
- 十进制转二进制
方法一:手动“拆数”,用位运算
想象一下,十进制转二进制就像是一场拆数游戏。我们要把一个十进制数拆成一个个 2 的幂次方的和。比如说要把 10 转换成二进制,我们就通过不断地将 10 除以 2 并记录余数,直到商为 0 。
#include <iostream>
#include <vector>void decimalToBinary(int decimal) {std::vector<int> binaryDigits;while (decimal > 0) {binaryDigits.push_back(decimal % 2);decimal /= 2;}for (auto it = binaryDigits.rbegin(); it != binaryDigits.rend(); ++it) {std::cout << *it;}std::cout << std::endl;
}
方法二:借助 bitset库
bitset库就像是一根魔法棒,能轻松帮我们把十进制数变成二进制。
#include <iostream>
#include <bitset>void decimalToBinaryWithBitset(int decimal) {std::bitset<32> binary(decimal);std::cout << binary << std::endl;
}
- 十进制转八进制
方法一:除8取余
把十进制数分成一个个“八人小组”,看看能分成多少组,还剩下多少人。通过不断地将十进制数除以 8 并记录余数,就能得到八进制数.
#include <iostream>
#include <vector>void decimalToOctal(int decimal) {std::vector<int> octalDigits;while (decimal > 0) {octalDigits.push_back(decimal % 8);decimal /= 8;}for (auto it = octalDigits.rbegin(); it != octalDigits.rend(); ++it) {std::cout << *it;}std::cout << std::endl;
}
方法二: sstream 库
sstream 库就像一支神奇画笔,能把十进制数“画”成八进制的样子。
#include <iostream>
#include <sstream>void decimalToOctalWithSstream(int decimal) {std::ostringstream oss;oss << std::oct << decimal;std::cout << oss.str() << std::endl;
}
- 十进制转十六进制
方法一:除16取余
把十进制数看作是一个装满宝藏的十六宫格,我们要通过除16取余的方式,看看每个宫格都藏了什么。对于10 - 15,我们分别用A - F表示。
#include <iostream>
#include <vector>void decimalToHexadecimal(int decimal) {std::vector<char> hexDigits;while (decimal > 0) {int remainder = decimal % 16;if (remainder < 10) {hexDigits.push_back(remainder + '0');} else {hexDigits.push_back(remainder - 10 + 'A');}decimal /= 16;}for (auto it = hexDigits.rbegin(); it != hexDigits.rend(); ++it) {std::cout << *it;}std::cout << std::endl;
}
方法二: sstream 库
#include <iostream>
#include <sstream>void decimalToHexadecimalWithSstream(int decimal) {std::ostringstream oss;oss << std::hex << decimal;std::cout << oss.str() << std::endl;
}
三、其他进制“回归”十进制
- 二进制转十进制
二进制转十进制就像是用积木搭建高楼,每一块积木都有它特定的价值。从二进制数的最低位开始,每一位乘以2的相应幂次并累加。
int binaryToDecimal(int binary) {int decimal = 0;int power = 0;while (binary > 0) {int digit = binary % 10;decimal += digit * (1 << power);binary /= 10;power++;}return decimal;
}
- 八进制转十进制
把八进制转十进制想象成是在弹奏一个八音盒,每个音符(八进制位)都有不同的音高(权重)。从八进制数的最低位开始,每一位乘以8的相应幂次并累加。
nt octalToDecimal(int octal) {int decimal = 0;int power = 0;while (octal > 0) {int digit = octal % 10;decimal += digit * (1 << power * 3);octal /= 10;power++;}return decimal;
}
- 十六进制转十进制
十六进制转十进制就像是在调一幅十六色的画,每种颜色(十六进制位)都有不同的分量(权重)。从十六进制数的最低位开始,每一位乘以16的相应幂次并累加,对于A - F,分别对应10 - 15。
int hexadecimalToDecimal(const std::string& hex) {int decimal = 0;int power = 0;for (auto it = hex.rbegin(); it != hex.rend(); ++it) {int digit;if (*it >= '0' && *it <= '9') {digit = *it - '0';} else if (*it >= 'A' && *it <= 'F') {digit = *it - 'A' + 10;} else if (*it >= 'a' && *it <= 'f') {digit = *it - 'a' + 10;}decimal += digit * (1 << power * 4);power++;}return decimal;
}