C 语言多进制间互转换
一、C 语言中的进制基础
1.1 常见进制概述
在计算机领域,我们经常会遇到不同进制的数字表示。常见的进制有十进制(Decimal)、二进制(Binary)、八进制(Octal)和十六进制(Hexadecimal)。
- 十进制:我们日常生活中最常用的进制,使用 0 - 9 这十个数字来表示数值。例如,数字 123 就是十进制数,它表示 1×10² + 2×10¹ + 3×10⁰。
- 二进制:计算机底层数据存储和处理所采用的进制,仅由 0 和 1 两个数字组成。在二进制中,每一位的权重是 2 的幂次方。例如,二进制数 101 表示 1×2² + 0×2¹ + 1×2⁰,换算成十进制就是 5。
- 八进制:由 0 - 7 这八个数字组成。八进制在早期的计算机系统中常用于表示文件权限等信息。在八进制中,每一位的权重是 8 的幂次方。例如,八进制数 34 表示 3×8¹ + 4×8⁰,换算成十进制为 28。
- 十六进制:使用 0 - 9 以及 A - F(或 a - f)来表示数值,其中 A - F 分别对应十进制的 10 - 15。十六进制常用于表示内存地址、颜色值等。在十六进制中,每一位的权重是 16 的幂次方。例如,十六进制数 0x2A(前缀 0x 表示这是一个十六进制数)表示 2×16¹ + 10×16⁰,换算成十进制是 42。
1.2 C 语言中不同进制的表示方式
在 C 语言中,不同进制的常量有不同的表示方法:
- 十进制常量:直接书写数字即可,例如 10、25、100 等。
- 二进制常量:在 C99 标准之后,可以使用前缀 0b 或 0B 来表示二进制常量。例如,0b101 表示二进制数 101,即十进制的 5。
- 八进制常量:以数字 0 开头表示八进制常量。例如,034 表示八进制数 34,换算成十进制是 28。
- 十六进制常量:以 0x 或 0X 开头表示十六进制常量。例如,0x2A 表示十六进制数 2A,即十进制的 42。
二、十进制与其他进制的转换
2.1 十进制转二进制
将十进制数转换为二进制数,常用的方法是除 2 取余法。具体步骤如下:
- 将十进制数除以 2,记录余数。
- 将商继续除以 2,再次记录余数,直到商为 0。
- 从下往上将记录的余数排列,即可得到对应的二进制数。
下面是一个 C 语言代码示例:
#include <stdio.h>
void decimalToBinary(int decimal) {
int binary[32];
int i = 0;
while (decimal > 0) {
binary[i] = decimal % 2;
decimal = decimal / 2;
i++;
}
for (int j = i - 1; j >= 0; j--) {
printf("%d", binary[j]);
}
}
int main() {
int decimal = 13;
printf("十进制数 %d 转换为二进制为: ", decimal);
decimalToBinary(decimal);
return 0;
}
2.2 十进制转八进制
十进制转八进制同样可以使用除 8 取余法,步骤与十进制转二进制类似:
- 将十进制数除以 8,记录余数。
- 将商继续除以 8,再次记录余数,直到商为 0。
- 从下往上将记录的余数排列,得到对应的八进制数。
以下是 C 语言代码示例:
#include <stdio.h>
void decimalToOctal(int decimal) {
int octal[32];
int i = 0;
while (decimal > 0) {
octal[i] = decimal % 8;
decimal = decimal / 8;
i++;
}
for (int j = i - 1; j >= 0; j--) {
printf("%d", octal[j]);
}
}
int main() {
int decimal = 50;
printf("十进制数 %d 转换为八进制为: ", decimal);
decimalToOctal(decimal);
return 0;
}
2.3 十进制转十六进制
十进制转十六进制使用除 16 取余法,不过在处理余数大于 9 时,需要将其转换为对应的十六进制字符(A - F)。步骤如下:
- 将十进制数除以 16,记录余数。
- 如果余数小于 10,直接记录;如果余数大于等于 10,将其转换为对应的十六进制字符(10 对应 A,11 对应 B,以此类推)。
- 将商继续除以 16,重复上述步骤,直到商为 0。
- 从下往上将记录的结果排列,得到对应的十六进制数。
以下是 C 语言代码示例:
#include <stdio.h>
void decimalToHexadecimal(int decimal) {
char hexadecimal[32];
int i = 0;
while (decimal > 0) {
int remainder = decimal % 16;
if (remainder < 10) {
hexadecimal[i] = remainder + '0';
} else {
hexadecimal[i] = remainder - 10 + 'A';
}
decimal = decimal / 16;
i++;
}
for (int j = i - 1; j >= 0; j--) {
printf("%c", hexadecimal[j]);
}
}
int main() {
int decimal = 255;
printf("十进制数 %d 转换为十六进制为: ", decimal);
decimalToHexadecimal(decimal);
return 0;
}
2.4 二进制、八进制、十六进制转十进制
- 二进制转十进制:将二进制数的每一位乘以 2 的相应幂次方,然后将结果相加。例如,对于二进制数 101,计算为 1×2² + 0×2¹ + 1×2⁰ = 5。
- 八进制转十进制:将八进制数的每一位乘以 8 的相应幂次方,然后将结果相加。例如,八进制数 34 计算为 3×8¹ + 4×8⁰ = 28。
- 十六进制转十进制:将十六进制数的每一位乘以 16 的相应幂次方,然后将结果相加。对于十六进制数 0x2A,计算为 2×16¹ + 10×16⁰ = 42。
以下是将二进制、八进制、十六进制转换为十进制的 C 语言代码示例:
#include <stdio.h>
#include <math.h>
int binaryToDecimal(char *binary) {
int decimal = 0;
int length = strlen(binary);
for (int i = 0; i < length; i++) {
decimal += (binary[i] - '0') * pow(2, length - 1 - i);
}
return decimal;
}
int octalToDecimal(char *octal) {
int decimal = 0;
int length = strlen(octal);
for (int i = 0; i < length; i++) {
decimal += (octal[i] - '0') * pow(8, length - 1 - i);
}
return decimal;
}
int hexadecimalToDecimal(char *hexadecimal) {
int decimal = 0;
int length = strlen(hexadecimal);
for (int i = 0; i < length; i++) {
if (hexadecimal[i] >= '0' && hexadecimal[i] <= '9') {
decimal += (hexadecimal[i] - '0') * pow(16, length - 1 - i);
} else if (hexadecimal[i] >= 'A' && hexadecimal[i] <= 'F') {
decimal += (hexadecimal[i] - 'A' + 10) * pow(16, length - 1 - i);
} else if (hexadecimal[i] >= 'a' && hexadecimal[i] <= 'f') {
decimal += (hexadecimal[i] - 'a' + 10) * pow(16, length - 1 - i);
}
}
return decimal;
}
int main() {
char binary[] = "101";
char octal[] = "34";
char hexadecimal[] = "2A";
printf("二进制数 %s 转换为十进制为: %d\n", binary, binaryToDecimal(binary));
printf("八进制数 %s 转换为十进制为: %d\n", octal, octalToDecimal(octal));
printf("十六进制数 %s 转换为十进制为: %d\n", hexadecimal, hexadecimalToDecimal(hexadecimal));
return 0;
}
三、二进制与八进制、十六进制的转换
3.1 二进制转八进制
由于 8 是 2 的 3 次方,所以二进制转八进制可以按三位一组进行转换。从二进制数的低位开始,每三位一组,不足三位的在高位补 0。然后将每组二进制数转换为对应的八进制数。
例如,对于二进制数 10110,分组为 010 110,010 转换为八进制是 2,110 转换为八进制是 6,所以 10110 转换为八进制是 26。
以下是 C 语言代码示例:
#include <stdio.h>
#include <string.h>
void binaryToOctal(char *binary) {
int length = strlen(binary);
int remainder = length % 3;
if (remainder!= 0) {
char newBinary[32];
int j = 0;
for (int i = 0; i < 3 - remainder; i++) {
newBinary[j++] = '0';
}
for (int i = 0; i < length; i++) {
newBinary[j++] = binary[i];
}
newBinary[j] = '\0';
strcpy(binary, newBinary);
}
length = strlen(binary);
for (int i = 0; i < length; i += 3) {
int group = (binary[i] - '0') * 4 + (binary[i + 1] - '0') * 2 + (binary[i + 2] - '0');
printf("%d", group);
}
}
int main() {
char binary[] = "10110";
printf("二进制数 %s 转换为八进制为: ", binary);
binaryToOctal(binary);
return 0;
}
3.2 二进制转十六进制
因为 16 是 2 的 4 次方,二进制转十六进制按四位一组进行转换。从二进制数的低位开始,每四位一组,不足四位的在高位补 0。然后将每组二进制数转换为对应的十六进制数。
例如,对于二进制数 1101110,分组为 0110 1110,0110 转换为十六进制是 6,1110 转换为十六进制是 E,所以 1101110 转换为十六进制是 6E。
以下是 C 语言代码示例:
#include <stdio.h>
#include <string.h>
void binaryToHexadecimal(char *binary) {
int length = strlen(binary);
int remainder = length % 4;
if (remainder!= 0) {
char newBinary[32];
int j = 0;
for (int i = 0; i < 4 - remainder; i++) {
newBinary[j++] = '0';
}
for (int i = 0; i < length; i++) {
newBinary[j++] = binary[i];
}
newBinary[j] = '\0';
strcpy(binary, newBinary);
}
length = strlen(binary);
for (int i = 0; i < length; i += 4) {
int group = (binary[i] - '0') * 8 + (binary[i + 1] - '0') * 4 + (binary[i + 2] - '0') * 2 + (binary[i + 3] - '0');
if (group < 10) {
printf("%d", group);
} else {
printf("%c", group - 10 + 'A');
}
}
}
int main() {
char binary[] = "1101110";
printf("二进制数 %s 转换为十六进制为: ", binary);
binaryToHexadecimal(binary);
return 0;
}
3.3 八进制转二进制
八进制转二进制,只需将八进制的每一位转换为对应的三位二进制数即可。
例如,八进制数 34,3 转换为二进制是 011,4 转换为二进制是 100,所以 34 转换为二进制是 011100。
以下是 C 语言代码示例:
#include <stdio.h>
#include <string.h>
void octalToBinary(char *octal) {
int length = strlen(octal);
for (int i = 0; i < length; i++) {
int digit = octal[i] - '0';
for (int j = 2; j >= 0; j--) {
printf("%d", (digit >> j) & 1);
}
}
}
int main() {
char octal[] = "34";
printf("八进制数 %s 转换为二进制为: ", octal);
octalToBinary(octal);
return 0;
}
3.4 十六进制转二进制
十六进制转二进制,将十六进制的每一位转换为对应的四位二进制数。对于十六进制字符 A - F(或 a - f),先转换为对应的十进制数 10 - 15,再转换为二进制。
例如,十六进制数 2A,2 转换为二进制是 0010,A(10)转换为二进制是 1010,所以 2A 转换为二进制是 00101010。
以下是 C 语言代码示例:
#include <stdio.h>
#include <string.h>
void hexadecimalToBinary(char *hexadecimal) {
int length = strlen(hexadecimal);
for (int i = 0; i < length; i++) {
if (hexadecimal[i] >= '0' && hexadecimal[i] <= '9') {
int digit = hexadecimal[i] - '0';
for (int j = 3; j >= 0; j--) {
printf("%d", (digit >> j) & 1);
}
} else if (hexadecimal[i] >= 'A' && hexadecimal[i] <= 'F') {
int digit = hexadecimal[i] - 'A' + 10;
for (int j = 3; j >= 0; j--) {
printf("%d", (digit >> j) & 1);
}
} else if (hexadecimal[i] >= 'a' && hexadecimal[i] <= 'f') {
int digit = hexadecimal[i] - 'a' + 10;
for (int j = 3; j >= 0; j--) {
printf("%d", (digit >> j) & 1);
}
}
}
}
int main() {
char hexadecimal[] = "2A";
printf("十六进制数 %s 转换为二进制为: ", hexadecimal);
hexadecimalToBinary(hexadecimal);
return 0;
}
3.5 八进制与十六进制的间接转换
由于八进制和十六进制之间没有直接简单的对应关系,我们可以通过十进制作为桥梁进行转换。即先将八进制转换为十进制,再将十进制转换为十六进制;或者先将十六进制转换为十进制,再将十进制转换为八进制。
以下是通过十进制进行八进制与十六进制转换的 C 语言代码示例:
#include <stdio.h>
#include <string.h>
#include <math.h>
int octalToDecimal(char *octal) {
int decimal = 0;
int length = strlen(octal);
for (int i = 0; i < length; i++) {
decimal += (octal[i] - '0') * pow(8, length - 1 - i);
}
return decimal;
}
void decimalToHexadecimal(int decimal) {
char hexadecimal[32];
int i = 0;
while (decimal > 0) {
int remainder = decimal % 16;
if (remainder < 10) {
hexadecimal[i] = remainder + '0';
} else {
hexadecimal[i] = remainder - 10 + 'A';
}
decimal = decimal / 16;
i++;
}
for (int j = i - 1; j >= 0; j--) {
printf("%c", hexadecimal[j]);
}
}
int hexadecimalToDecimal(char *hexadecimal) {
int decimal = 0;
int length = strlen(hexadecimal);
for (int i = 0; i < length; i++) {
if (hexadecimal[i] >= '0' && hexadecimal[i] <= '9') {
decimal += (hexadecimal[i] - '0') * pow(16, length - 1 - i);
} else if (hexadecimal[i] >= 'A' && hexadecimal[i] <= 'F') {
decimal += (hexadecimal[i] - 'A' + 10) * pow(16, length - 1 - i);
} else if (hexadecimal[i] >= 'a' && hexadecimal[i] <= 'f') {
decimal += (hexadecimal[i] - 'a' + 10) * pow(16, length - 1 - i);
}
}
return decimal;
}
void decimalToOctal(int decimal) {
int octal[32];
int i = 0;
while (decimal > 0) {
octal[i] = decimal % 8;
decimal = decimal / 8;
i++;
}
for (int j = i - 1; j >= 0; j--) {
printf("%d", octal[j]);
}
}
int main() {
char octal[] = "34";
char hexadecimal[] = "2A";
printf("八进制数 %s 转换为十六进制为: ", octal);
int decimal = octalToDecimal(octal);
decimalToHexadecimal(decimal);
printf("\n");
printf("十六进制数 %s 转换为八进制为: ", hexadecimal);
decimal = hexadecimalToDecimal(hexadecimal);
decimalToOctal(decimal);
printf("\n");
return 0;
}
四、实际应用场景
4.1 计算机底层数据处理
在计算机底层,如操作系统内核、驱动程序开发等场景中,经常需要对二进制数据进行处理。了解不同进制间的转换对于理解内存中的数据存储、位操作等非常重要。例如,在处理硬件寄存器的值时,常常需要将二进制数据转换为更易读的十六进制来进行调试和分析。
4.2 网络编程
在网络编程中,IP 地址的表示和处理涉及到进制转换。IP 地址通常以点分十进制的形式表示(如 192.168.1.1),但在网络传输中实际是以二进制形式存在。程序员需要能够在不同表示形式之间进行转换,以实现正确的网络通信和地址解析。
4.3 图形图像处理
在图形图像处理领域,颜色值常以十六进制表示。例如,RGB 颜色模式中,每种颜色分量(红、绿、蓝)可以用一个十六进制数表示。了解进制转换有助于在程序中对颜色值进行操作和处理,如颜色混合、亮度调整等。
通过对 C 语言中多进制间互转换的深入学习和实践,我们能够更好地理解计算机数据的表示和处理方式,为编写高效、灵活的程序奠定坚实的基础。无论是在底层系统开发还是应用层编程中,进制转换的知识都具有重要的实用价值。在实际编程过程中,我们应根据具体需求选择合适的算法和数据结构来实现进制转换,以提高程序的性能和可读性。同时,不断练习和优化代码,能够使我们在面对各种复杂的进制转换任务时更加得心应手。