赞
踩
进制 | 前缀表示 | 整数常量示例 | 转换库接口 | 参数及返回值示例 |
---|---|---|---|---|
二进制 | 0b 或 0B | 0b1010 | std::bitset<> | std::bitset<8> binary(42); std::bitset<8> binary(“101010”); |
八进制 | 0 | 075 | std::oct | std::cout << std::oct << 42; int oct_num = std::stoi(“52”, nullptr, 8); |
十进制 | 无前缀 | 42 | std::dec | std::cout << std::dec << 42; int dec_num = std::stoi(“42”, nullptr, 10); |
十六进制 | 0x 或 0X | 0x2A | std::hex | std::cout << std::hex << 42; int hex_num = std::stoi(“2A”, nullptr, 16); |
在计算机科学中,进制转换是一种非常重要的概念。它涉及将一个数值从一个进制系统(比如二进制、八进制、十进制或十六进制)转换到另一个进制系统。在C/C++编程语言中,我们通常会遇到需要对数值进行进制转换的情况,以满足不同的计算需求或实现特定功能。C/C++ 提供了多种进制转换方法,使得程序员能够方便地在不同进制系统之间进行转换。
在C/C++编程语言中,整数常量可以根据其前缀以不同的进制进行表示:
0b
或0B
为前缀的整数常量表示二进制数(例如:0b1010)0
为前缀的整数常量表示八进制数(例如:075)0x
或0X
为前缀的整数常量表示十六进制数(例如:0x2A)此外,在C++中,还可以使用std::bitset
类、std::stoi
函数和std::stoi
函数等库功能实现进制转换。
在以下章节中,我们将依次介绍C/C++进行进制转换的底层原理、基本方法和高级应用。希望能够帮助读者更深入地理解C/C++进制转换的原理和技巧,为实际编程工作提供参考。
进制转换在计算机科学和C/C++编程中具有重要的地位,因为它广泛应用于各种实际场景,包括数据存储、通信、加密和解密等。具体的应用场景如下:
这些都是为什么熟练掌握C/C++进制转换技巧极为重要的原因。在后续章节中,我们将详细介绍底层原理、基本方法以及高级应用,助您深入了解和掌握C/C++进制转换的相关知识。
为了帮助读者全面了解C/C++进制转换的相关知识,本文将从以下几个方面进行深入介绍:
通过对以上内容的深入讨论,我们希望能够帮助读者全面掌握C/C++的进制转换知识,为实际应用提供有力支持。在阅读本文的过程中,建议读者动手实践每个章节的示例代码,以更好地理解和掌握C/C++进制转换的技巧。
在计算机科学中,进制指的是数字系统的基数,也就是计算一个数值所用的基本单位数量。下面简要介绍四种常用的进制系统:
了解这些进制系统对于理解C/C++中的进制转换至关重要,接下来我们将讨论C/C++进制转换的基本原理。
在C/C++编程中,使用进制转换技巧主要是为了在不同进制之间表示和处理数据。以下简要介绍C/C++进制转换的基本原理:
通过理解C/C++进制转换的基本原理,我们可以更好地掌握在编程中如何在不同进制之间表示和处理数据。接下来,我们将探讨类型转换与进制转换之间的关系。
类型转换和进制转换是C/C++编程中两个密切相关的概念,它们在实际编程应用中起到了关键作用。下面简要介绍它们之间的关系:
int
类型的值转换为float
类型的值。类型转换可以分为隐式类型转换和显式类型转换。隐式类型转换是编译器自动进行的转换,例如将一个较小的整数类型值赋给一个较大的整数类型变量。显式类型转换是程序员通过类型转换运算符(如static_cast
)手动进行的转换。std::stoi
、std::stol
等。通过深入理解类型转换与进制转换之间的关系,我们可以更好地掌握C/C++编程中涉及进制转换的问题,并为实际应用提供有效解决方案。
在C/C++编程中,要将八进制数与十六进制数进行互相转换,通常需要经过以下几个步骤:
以下是具体的转换示例:
#include <iostream>
#include <cstdio>
#include <sstream>
int main() {
std::string octal_str = "75";
int decimal_num;
// 将八进制字符串转换为十进制整数
std::istringstream(octal_str) >> std::oct >> decimal_num;
// 将十进制整数转换为十六进制字符串
std::stringstream hex_ss;
hex_ss << std::hex << decimal_num;
std::string hexadecimal_str = hex_ss.str();
std::cout << "Hexadecimal: " << hexadecimal_str << std::endl;
return 0;
}
#include <iostream>
#include <cstdio>
#include <sstream>
int main() {
std::string hex_str = "2A";
int decimal_num;
// 将十六进制字符串转换为十进制整数
std::istringstream(hex_str) >> std::hex >> decimal_num;
// 将十进制整数转换为八进制字符串
std::stringstream octal_ss;
octal_ss << std::oct << decimal_num;
std::string octal_str = octal_ss.str();
std::cout << "Octal: " << octal_str << std::endl;
return 0;
}
通过上述示例,我们可以学会在C/C++中实现八进制与十六进制的互相转换。接下来,我们将介绍如何在八进制与十进制之间进行转换。
在C/C++编程中,要实现八进制与十进制之间的转换,我们可以使用标准库函数和流操作进行转换。
以下是具体的转换示例:
#include <iostream>
#include <sstream>
int main() {
std::string octal_str = "75";
int decimal_num;
// 将八进制字符串转换为十进制整数
std::istringstream(octal_str) >> std::oct >> decimal_num;
std::cout << "Decimal: " << decimal_num << std::endl;
return 0;
}
#include <iostream>
#include <sstream>
int main() {
int decimal_num = 61;
std::stringstream octal_ss;
// 将十进制整数转换为八进制字符串
octal_ss << std::oct << decimal_num;
std::string octal_str = octal_ss.str();
std::cout << "Octal: " << octal_str << std::endl;
return 0;
}
通过上述示例,我们可以学会如何在C/C++中实现八进制与十进制之间的转换。下一节,我们将介绍如何在十进制与十六进制之间进行转换。
在C/C++编程中,要实现二进制与八进制之间的转换,我们可以使用一些标准库函数和流操作进行转换。
以下是具体的转换示例:
#include <iostream>
#include <bitset>
#include <sstream>
int main() {
std::string binary_str = "101010";
std::bitset<32> binary_bitset(binary_str);
std::stringstream octal_ss;
// 将二进制字符串转换为对应的十进制整数
unsigned long decimal_num = binary_bitset.to_ulong();
// 将十进制整数转换为八进制字符串
octal_ss << std::oct << decimal_num;
std::string octal_str = octal_ss.str();
std::cout << "Octal: " << octal_str << std::endl;
return 0;
}
#include <iostream>
#include <bitset>
#include <sstream>
int main() {
std::string octal_str = "52";
int decimal_num;
// 将八进制字符串转换为十进制整数
std::istringstream(octal_str) >> std::oct >> decimal_num;
// 将十进制整数转换为二进制字符串
std::bitset<32> binary_bitset(decimal_num);
std::string binary_str = binary_bitset.to_string();
// 去除字符串前导零
size_t non_zero_pos = binary_str.find_first_not_of('0');
binary_str = binary_str.substr(non_zero_pos);
std::cout << "Binary: " << binary_str << std::endl;
return 0;
}
通过上述示例,我们可以学会如何在C/C++中实现二进制与八进制之间的转换。接下来,我们将介绍如何在二进制与十进制之间进行转换。
在C/C++编程中,要实现二进制与十进制之间的转换,我们可以使用一些标准库函数和流操作进行转换。
以下是具体的转换示例:
#include <iostream>
#include <bitset>
int main() {
std::string binary_str = "101010";
std::bitset<32> binary_bitset(binary_str);
// 将二进制字符串转换为对应的十进制整数
unsigned long decimal_num = binary_bitset.to_ulong();
std::cout << "Decimal: " << decimal_num << std::endl;
return 0;
}
#include <iostream>
#include <bitset>
int main() {
int decimal_num = 42;
// 将十进制整数转换为二进制字符串
std::bitset<32> binary_bitset(decimal_num);
std::string binary_str = binary_bitset.to_string();
// 去除字符串前导零
size_t non_zero_pos = binary_str.find_first_not_of('0');
binary_str = binary_str.substr(non_zero_pos);
std::cout << "Binary: " << binary_str << std::endl;
return 0;
}
通过上述示例,我们可以学会如何在C/C++中实现二进制与十进制之间的转换。接下来,我们将介绍如何在二进制与十六进制之间进行转换。
在C/C++编程中,要实现二进制与十六进制之间的转换,我们可以使用一些标准库函数和流操作进行转换。
以下是具体的转换示例:
#include <iostream>
#include <bitset>
#include <sstream>
int main() {
std::string binary_str = "101010";
std::bitset<32> binary_bitset(binary_str);
std::stringstream hex_ss;
// 将二进制字符串转换为对应的十进制整数
unsigned long decimal_num = binary_bitset.to_ulong();
// 将十进制整数转换为十六进制字符串
hex_ss << std::hex << decimal_num;
std::string hex_str = hex_ss.str();
std::cout << "Hexadecimal: " << hex_str << std::endl;
return 0;
}
#include <iostream>
#include <bitset>
#include <sstream>
int main() {
std::string hex_str = "2A";
int decimal_num;
// 将十六进制字符串转换为十进制整数
std::istringstream(hex_str) >> std::hex >> decimal_num;
// 将十进制整数转换为二进制字符串
std::bitset<32> binary_bitset(decimal_num);
std::string binary_str = binary_bitset.to_string();
// 去除字符串前导零
size_t non_zero_pos = binary_str.find_first_not_of('0');
binary_str = binary_str.substr(non_zero_pos);
std::cout << "Binary: " << binary_str << std::endl;
return 0;
}
通过上述示例,我们可以学会如何在C/C++中实现二进制与十六进制之间的转换。接下来,我们将介绍有关符号数进制转换的方法。
对于带符号数(signed numbers)的进制转换,我们需要考虑数值的符号以及处理负数时的二进制表示法(通常使用补码表示法)。以下是一些建议和示例以实现带符号数的进制转换。
注意:在负数二进制表示中,最高位(最左边)表示符号位,1
表示负数,0
表示正数。
将一个负数转换为补码表示法,需要执行以下步骤:
0
变为1
,将1
变为0
)。1
。例:将-5
以补码形式表示为8位二进制数
1. 绝对值的二进制表示为:0000 0101
2. 按位取反得到: 1111 1010
3. 加1得到补码: 1111 1011
要将负数的二进制转换为十进制,务必先将这个数从补码形式转换为其真实的十进制表示,然后根据符号位决定是否将十进制值设为负数。
以下是一个使用C++进行带符号数二进制与十进制转换的示例:
#include <iostream>
#include <bitset>
#include <cstdint>
int main() {
std::string binary_str = "11111011"; // 补码形式表示的 -5
std::bitset<8> binary_bitset(binary_str);
// 将二进制字符串转换为对应的(有符号)十进制整数
int8_t decimal_num = static_cast<int8_t>(binary_bitset.to_ulong());
std::cout << "Decimal: " << static_cast<int>(decimal_num) << std::endl;
return 0;
}
这些示例和建议可以帮助您更好地理解和实现带符号数的进制转换。在实际编程中,请根据自己的需求选择合适的方法和函数。在处理有符号数时,请务必注意数值的范围以避免溢出。
在将带符号数进行进制转换时,我们需要首先确定符号位。对于负数,需要采用补码表示。在接下来的部分中,我将提供数学方法以实现各种进制之间的转换。
以二进制和十进制间互转为例:
例如,将二进制数 1101 转换为十进制时,按权展开:
(1 × 2^3) + (1 × 2^2) + (0 × 2^1) + (1 × 2^0) = 8 + 4 + 0 + 1 = 13。
例如,将十进制数 13 转换为二进制时,执行连续除法:
13 ÷ 2 = 6 ...余 1
6 ÷ 2 = 3 ...余 0
3 ÷ 2 = 1 ...余 1
1 ÷ 2 = 0 ...余 1
由此得到二进制数 1101。
对于负数,首先将其绝对值转换为二进制,然后转换为补码表示。
例如,将 -13 转换为二进制:
下面是将补码表示的负数从二进制转换为十进制的方法:
例如,将补码形式表示的二进制数 1111 转换为十进制数:
对于八进制和十六进制与其他进制的转换,可以先将数值转换为二进制,然后再转换为目标进制。
对于小数部分,我们可以使用类似的方法进行进制转换。这里我们以二进制和十进制之间的互相转换为例:
例如,将二进制小数 0.1101 转换为十进制小数:
按权展开:(1 × 2^-1) + (1 × 2^-2) + (0 × 2^-3) + (1 × 2^-4) = 0.5 + 0.25 + 0 + 0.0625 = 0.8125。
例如,将十进制小数 0.8125 转换为二进制小数:
执行连续乘法,将乘法结果的整数部分一次提取出来,直到其结果为 0 或达到所需的精度:
0.8125 × 2 = 1.625 ...提取 1
0.6250 × 2 = 1.250 ...提取 1
0.2500 × 2 = 0.500 ...提取 0
0.5000 × 2 = 1.000 ...提取 1
将提取的整数部分依次排列:1101;从而得到二进制小数 0.1101。
对于小数部分的八进制、十六进制与其他进制之间的转换,与上述过程类似。可以先将小数转换为二进制形式,然后再将其转换为目标进制。在实际应用中,注意控制所需的精度以避免无限循环小数的出现。
下表总结了二进制、八进制、十进制和十六进制之间的数学转换方法与代码转换方法。
转换类型 | 数学方法 | 代码方法(C++) |
---|---|---|
二进制 -> 十进制 | 按权展开求和 | 使用 std::bitset 将二进制字符串转换为 unsigned long |
十进制 -> 二进制 | 连续除法求余 | 使用 std::bitset 将整数转换为二进制字符串 |
八进制 -> 十进制 | 按权展开求和 | 使用 std::istringstream 将八进制字符串转换为整数 |
十进制 -> 八进制 | 连续除法求余 | 使用 std::stringstream 将整数转换为八进制字符串 |
十六进制 -> 十进制 | 按权展开求和 | 使用 std::istringstream 将十六进制字符串转换为整数 |
十进制 -> 十六进制 | 连续除法求余 | 使用 std::stringstream 将整数转换为十六进制字符串 |
符号数二进制 -> 十进制 | 补码形式的逆过程求和 | 使用 std::bitset 将补码形式的二进制字符串转换为整数 |
符号数十进制 -> 二进制 | 按补码形式转换 | 使用 std::bitset 将整数转换为补码形式的二进制字符串 |
小数二进制 -> 十进制 | 按权展开求和 | 使用类似按权展开的自定义实现 |
小数十进制 -> 二进制 | 连续乘法求整数部分 | 使用类似连续乘法的自定义实现 |
扩展内容:
BaseConverter
类的实现以下是一个 BaseConverter
类的实现,它具有所需的功能。
首先,定义一个结构体 NumberRepresentation
以存储各种进制的数值表示:
#include <string>
#include <iostream>
#include <sstream>
#include <bitset>
struct NumberRepresentation {
std::string binary;
std::string octal;
std::string decimal;
std::string hexadecimal;
};
然后,创建一个进制转换类 BaseConverter
,实现所需的功能:
class BaseConverter {
public:
NumberRepresentation convert(int number) {
NumberRepresentation num_repr;
num_repr.binary = int_to_binary(number);
num_repr.octal = int_to_octal(number);
num_repr.decimal = std::to_string(number);
num_repr.hexadecimal = int_to_hex(number);
return num_repr;
}
std::string hex_array_to_string(const uint8_t *hex_array, size_t size) {
std::stringstream ss;
ss << std::hex;
for (size_t i = 0; i < size; ++i) {
ss << static_cast<int>(hex_array[i]);
}
return ss.str();
}
// 提供数学转换接口,不使用C++ API
int binary_to_decimal_math(const std::string& binary) {
int decimal = 0;
for (size_t i = 0; i < binary.length(); ++i) {
decimal = decimal * 2 + (binary[i] - '0');
}
return decimal;
}
std::string decimal_to_binary_math(int decimal) {
std::string binary;
while (decimal > 0) {
binary = std::to_string(decimal % 2) + binary;
decimal /= 2;
}
return binary;
}
int octal_to_decimal_math(const std::string& octal) {
int decimal = 0;
for (size_t i = 0; i < octal.length(); ++i) {
decimal = decimal * 8 + (octal[i] - '0');
}
return decimal;
}
std::string decimal_to_octal_math(int decimal) {
std::string octal;
while (decimal > 0) {
octal = std::to_string(decimal % 8) + octal;
decimal /= 8;
}
return octal;
}
int hexadecimal_to_decimal_math(const std::string& hex) {
int decimal = 0;
for (size_t i = 0; i < hex.length(); ++i) {
char digit = hex[i];
int value;
if ('0' <= digit && digit <= '9') {
value = digit - '0';
} else if ('A' <= digit && digit <= 'F') {
value = digit - 'A' + 10;
} else if ('a' <= digit && digit <= 'f') {
value = digit - 'a' + 10;
} else {
throw std::invalid_argument("Invalid hexadecimal character");
}
decimal = decimal * 16 + value;
}
return decimal;
}
std::string decimal_to_hexadecimal_math(int decimal) {
const char* hex_digits = "0123456789ABCDEF";
std::string hex;
while (decimal > 0) {
hex = hex_digits[decimal % 16] + hex;
decimal /= 16;
}
return hex;
}
double binary_fraction_to_decimal_math(const std::string& binary_fraction) {
double decimal = 0;
double mult = 0.5;
for (char ch : binary_fraction) {
decimal += (ch - '0') * mult;
mult *= 0.5;
}
return decimal;
}
std::string decimal_fraction_to_binary_math(double decimal_fraction, int precision) {
std::string binary_fraction;
while (precision > 0 && decimal_fraction > 0) {
decimal_fraction *= 2;
binary_fraction += (decimal_fraction >= 1) ? '1' : '0';
if (decimal_fraction >= 1) {
decimal_fraction -= 1;
}
--precision;
}
return binary_fraction;
}
private:
std::string int_to_binary(int number) {
std::bitset<32> binary_bitset(number);
std::string binary_str = binary_bitset.to_string();
size_t non_zero_pos = binary_str.find_first_not_of('0');
return binary_str.substr(non_zero_pos);
}
std::string int_to_octal(int number) {
std::stringstream ss;
ss << std::oct << number;
return ss.str();
}
std::string int_to_hex(int number) {
std::stringstream ss;
ss << std::hex << number;
return ss.str();
}
};
现在,您可以使用这个类进行进制转换和其他相关任务。例如:
int main() {
BaseConverter converter;
int input_number = 42;
NumberRepresentation num_repr = converter.convert(input_number);
std::cout << "Binary: " << num_repr.binary << std::endl;
std::cout << "Octal: " << num_repr.octal << std::endl;
std::cout << "Decimal: " << num_repr.decimal << std::endl;
std::cout << "Hexadecimal: " << num_repr.hexadecimal << std::endl;
uint8_t hex_array[] = {0x74, 0x65, 0x73, 0x74};
std::string hex_str = converter.hex_array_to_string(hex_array, sizeof(hex_array) / sizeof(uint8_t));
std::cout << "Hexadecimal string: " << hex_str << std::endl;
return 0;
}
在这个例子中,我们定义了一个结构体 NumberRepresentation
和一个进制转换类 BaseConverter
,类中实现了所需的功能。类的方法可以为整数生成二进制、八进制、十进制和十六进制表示,将十六进制数组转换为字符串,以及提供数学转换接口(这些接口需要自行根据前述数学方法来实现)。
在实际应用中,我们可能需要将不同进制的数值表示从文件、网络传输或其他源中读入,并将其转换为整数或浮点数以进行进一步处理。同样地,我们也可能需要将整数或浮点数转换为其他进制的形式,以便进行输出或传输。
从文件或其他源中读取不同进制的表示时,需要了解该表示的格式。例如,二进制前面通常有 “0b” 或 “0B” 前缀,八进制有 “0” 前缀,十六进制有 “0x” 或 “0X” 前缀。读取过程中需忽略这些前缀,并将后续的字符读入字符串或字符数组进行进一步处理。
写入不同进制表示时,通常需要为输出的字符串添加相应的前缀。添加前缀有助于在后续读取时识别不同的数值表示和进制。
位操作符允许我们直接操作整数的二进制位。这可以让我们高效地实现二进制与其他进制之间的转换。位操作符包括:按位与(&),按位或(|),按位异或(^),按位非(~),左移(<<),右移(>>)等。
在进制转换过程中,位操作符可以帮助我们直接访问和修改数值的二进制位,从而简化计算过程。例如,对于加法和乘法等基本运算,可以通过按位操作实现而无需真正执行加法和乘法。同时,在需要高效执行的场景中(如网络编程、加密算法等),位操作符在性能上的优势使得它成为实现进制转换等操作的首选。
在实际编程中,结合具体问题和项目需求,我们可以灵活选择是否使用位操作符。选择使用位操作符时需要考虑到代码的可读性和性能。在一些情况下,使用位操作符可以提高代码性能,但可能会降低代码可读性。在这种情况下,我们需要在性能与可读性之间进行权衡。
使用位操作符实现的进制转换算法与前述的除法和乘法运算相似。例如,将一个十进制整数转换为二进制字符串时,可以使用右移操作符逐位读取整数的二进制表示:
std::string decimal_to_binary_bitwise(int decimal) {
std::string binary;
for (int i = 31; i >= 0; --i) {
binary += ((decimal >> i) & 1) ? '1' : '0';
}
size_t non_zero_pos = binary.find_first_not_of('0');
return binary.substr(non_zero_pos);
}
该函数首先创建一个空的二进制字符串。然后,从最高位(第31位)开始,逐位进行以下操作:使用右移操作符将当前位移动到二进制表示的最低位(第0位),然后用按位与操作符 & 和 1 进行按位与运算。这样可以得到当前位的值(0 或 1)。将这个值转换为字符并添加到二进制字符串中。
最后,使用 find_first_not_of
函数找到第一个不是 ‘0’ 的字符的位置,从该位置开始截取子字符串,以去除前导零。这样,我们使用位操作符实现了十进制整数到二进制字符串的转换。在实际应用中,还可以类似地使用位操作符实现其他进制间的转换。
在某些应用场景中,例如网络协议或加密技术等,位操作符特别适用。使用位操作符进行进制转换可以实现高效的算法,提高程序的性能。
许多网络协议(如 IPv4、IPv6 或 TCP/IP 等)在传输数据时需要操作二进制位。在这些场景中,位操作符可以实现高效的算法,达到更好的性能。
例如,IPv4 地址通常表示为 4 个十进制整数(每个范围在 0-255 之间),用英文句点分隔。但在实际中,IPv4 地址是 32 位的二进制整数。使用位操作符可以方便地在二进制和点分十进制之间进行转换。例如,IP 地址子网掩码的计算就需要用到位操作符。
在加密技术中,密钥和明文往往需要进行位级别的操作以产生密文。例如,DES(Data Encryption Standard)加密算法中,在密钥生成和加密过程中大量使用了位操作符。进行置换、选择、异或等操作时,位操作符可以简化实现过程,提高计算速度。
通过这些实际应用案例,可以看到位操作符在进制转换以及其他处理二进制位的场景中具有明显的性能优势。在性能敏感的场合,使用位操作符进行进制转换和其他二进制位操作是一个理想的选择。同时,我们需要权衡代码的可读性和性能,因此在不同的场景下,我们可以根据需要灵活地选择使用位操作符或其他方法。
C++ 标准库提供了一些实用功能,可帮助我们进行进制转换。例如,可以使用 <bitset>
处理二进制字符串,<sstream>
实现进制间的转换等。比如以下示例:
#include <bitset>
std::string int_to_binary(int integer) {
std::bitset<32> binary_bitset(integer);
return binary_bitset.to_string();
}
在这个例子中,我们将整数转换为一个包含 32 位的 bitset
。接着,我们使用 bitset
的 to_string()
函数将其转换为二进制字符串。需要注意的是,bitset::to_string()
生成的字符串可以包含前导零,根据需求可以选择进一步处理结果。
#include <sstream>
#include <iomanip>
int hex_to_decimal(const std::string& hexadecimal) {
int decimal;
std::stringstream ss(hexadecimal);
ss >> std::hex >> decimal;
return decimal;
}
在此示例中,我们将十六进制字符串转换为十进制整数。首先,我们创建一个 stringstream
对象并将十六进制字符串输入其中。然后使用 std::hex
修饰符指定我们将从 stringstream 读取十六进制整数。最后,通过将 stringstream 对象转换为整数,实现进制间的转换。
在实际项目中,可以根据性能需求和代码可读性来决定是使用位操作符实现进制转换,还是使用 C++ 标准库中提供的功能。在很多情况下,使用 C++ 标准库的功能具有良好的代码可读性,且性能足够满足需求。
本章将提供一些针对进制转换的面试题。这些题目主要分为以下几个部分:
这部分面试题主要测试对进制转换基本概念的理解和基本编程能力。
问题描述:给定一个非负整数 n,要求将其转换为二进制字符串。
要求:
string decimal_to_binary(int n)
,输入为非负整数 n,输出为二进制字符串。示例:
输入: 2
输出: "10"
输入: 10
输出: "1010"
问题描述:给定一个整数 n,要求将其转换为十六进制字符串。注意:负整数应当用补码表示。
要求:
string decimal_to_hex(int n)
,输入为整数 n,输出为十六进制字符串。示例:
输入: 26
输出: "1A"
输入: -1
输出: "FFFFFFFF"
问题描述:给定一个二进制字符串 s,要求将其转换为十进制整数。
要求:
int binary_to_decimal(const string &s)
,输入为二进制字符串 s,输出为十进制整数。示例:
输入: "11010"
输出: 26
输入: "1010"
输出: 10
这部分面试题较复杂,测试在实际应用中处理较为复杂的进制转换问题的能力。
问题描述:给定两个二进制字符串 a 和 b,返回它们的和(用二进制表示)。
要求:
string add_binary(const string &a, const string &b)
,输入为两个二进制字符串 a 和 b,输出为它们的和(二进制表示)。示例:
输入: a = "1010", b = "110"
输出: "10000"
问题描述:给定一个有效的 IPv4 地址 ip,使用点分十进制格式表示。请实现一个函数,将给定的 IPv4 地址从十进制点分表示法转换为 32 位二进制整数表示。
要求:
uint32_t ipv4_decimal_to_binary(const string &ip)
,输入为一个表示 IPv4 地址的字符串,输出为 32 位二进制整数。示例:
输入: ip = "192.168.1.1"
输出: 3232235777
问题描述:给定两个整数 x 和 y,计算它们的汉明距离。汉明距离(Hamming distance)是相应位置上二进制数值不同的位数。
要求:
int hamming_distance(int x, int y)
,输入为两个整数 x 和 y,输出为它们的汉明距离。示例:
输入: x = 1, y = 4
输出: 2
原因:
1 (0 0 0 1)
4 (0 1 0 0)
↑ ↑
这部分面试题将进制转换与其他领域(如数据结构、算法等)相结合,测试在实际项目中处理更加负责的问题的能力。
问题描述:给定一个由 0 和 1 组成的二叉树,每个根到叶路径表示一个二进制数。从上到下遍历,指定的一个路径构成的二进制数,请计算所有路径的和。
要求:
int sum_root_to_leaf(TreeNode* root)
,输入为二叉树的根节点,输出为所有二进制路径和。示例:
输入:
1
/ \
0 1
/ \ / \
1 0 0 1
输出: 22
解释:
(100)1 + (101)5 + (110)6 + (111)7 = 22
问题描述:UTF-8 是一种变长字节编码,用于表示 Unicode 编码的字符。请验证给定的字节数组是否表示有效的 UTF-8 编码。
要求:
bool is_valid_utf8(const vector<int>& data)
,输入为表示字节的整数数组,输出为布尔值,表示输入是否为有效的 UTF-8 编码。示例:
输入: data = [197, 130, 1]
输出: true
解释: 这是有效的 UTF-8 编码,表示字母 "ć"(U+0107)。
问题描述:给定一个整数,实现整数与字母之间的相互转换。从 1 开始,分别表示字母 A 到 Z。例如,1 对应 A,2 对应 B,…,26 对应 Z。要求不使用任何库函数。
要求:
string int_to_alpha(int n)
和 int alpha_to_int(const string& s)
,分别将整数转换为字母字符串和将字母字符串转换为整数。示例:
输入: 28
输出: "AB"
输入: "AB"
输出: 28
string decimal_to_binary(int n) {
if (n == 0) {
return "0";
}
string result;
while (n > 0) {
result = (n % 2 ? '1' : '0') + result;
n /= 2;
}
return result;
}
string decimal_to_hex(int n) {
if (n == 0) {
return "0";
}
const char* hex_digits = "0123456789ABCDEF";
string result;
for (int i = 7; i >= 0; --i) {
result += hex_digits[(n >> (i * 4)) & 0xf];
}
size_t non_zero_pos = result.find_first_not_of('0');
return result.substr(non_zero_pos);
}
int binary_to_decimal(const string &s) {
int result = 0;
for (const char c : s) {
result = result * 2 + (c - '0');
}
return result;
}
string add_binary(const string &a, const string &b) {
string result;
int i = a.size() - 1, j = b.size() - 1;
int carry = 0;
while (i >= 0 || j >= 0) {
int sum = carry + (i >= 0 ? a[i--] - '0' : 0) + (j >= 0 ? b[j--] - '0' : 0);
result = (sum % 2 ? '1' : '0') + result;
carry = sum / 2;
}
if (carry) {
result = '1' + result;
}
return result;
}
uint32_t ipv4_decimal_to_binary(const string &ip) {
uint32_t result = 0;
int num = 0, count = 0;
for (const char c : ip) {
if (c == '.') {
result = (result << 8) | num;
num = 0;
++count;
} else {
num = num * 10 + (c - '0');
}
}
result = (result << 8) | num;
return result;
}
int hamming_distance(int x, int y) {
int xor_result = x ^ y;
int distance = 0;
while (xor_result) {
distance += xor_result & 1;
xor_result >>= 1;
}
return distance;
}
int sum_path(TreeNode* node, int path_val) {
path_val = (path_val << 1) | node -> val;
if (!node -> left && !node -> right) {
return path_val;
}
int total_sum = 0;
if (node -> left) {
total_sum += sum_path(node -> left, path_val);
}
if (node -> right) {
total_sum += sum_path(node -> right, path_val);
}
return total_sum;
}
int sum_root_to_leaf(TreeNode* root) {
if (!root) {
return 0;
}
return sum_path(root, 0);
}
bool is_valid_utf8(const vector<int>& data) {
int n_bytes = 0;
for (int byte : data) {
if (n_bytes == 0) {
if (byte >> 5 == 0b110) n_bytes = 1;
else if (byte >> 4 == 0b1110) n_bytes = 2;
else if (byte >> 3 == 0b11110) n_bytes = 3;
else if (byte >> 7 != 0) return false;
} else {
if (byte >> 6 != 0b10) return false;
n_bytes--;
}
}
return n_bytes == 0;
}
string int_to_alpha(int n) {
if (n <= 0) {
return "";
}
string result;
while (n > 0) {
result = char('A' + (n - 1) % 26) + result;
n = (n - 1) / 26;
}
return result;
}
int alpha_to_int(const string& s) {
int result = 0;
for (const char c : s) {
result = result * 26 + (c - 'A' + 1);
}
return result;
}
经过前五章的学习,我们发现进制转换不仅是编程领域中的基础知识,而且对提高逻辑思维能力和解决实际问题具有很大的帮助。从心理学的角度来看,掌握进制转换原理以及相关应用不仅有助于提升对数学思维的理解,还有利于培养求知欲和语言表达能力。
通过本博客所涉及的实例和面试题,我们可以看到进制转换在计算机科学领域中具有广泛的应用,涉及数据结构、网络编程、编码等多个方面。不论是用于工作还是面试,这些知识点都会为你带来独特的优势。同时,编程面试中出现的进制转换相关问题往往需要在有限的时间内找到合适的解决方案,因此从心理学的角度来说,这些问题具有挑战性,有助于锻炼思维能力和建立心理承受压力的机制。
在未来的工作与学习中,我们相信掌握好进制转换技能将在各个领域产生深远的影响。在本博客的学习过程中,希望大家积极参与讨论,增进共同的理解,并将所学应用到实际问题中。同时,我们期待你将所学到的知识和面试题应用于实际项目中,为计算机科学发展做出更多的贡献。
感谢你的阅读与支持!如果你觉得这篇博客对你的学习有所帮助,欢迎点击收藏并点赞。期待我们在学习的道路上相互激励,共同成长!如有任何问题和建议,欢迎在评论区留言讨论,我们将尽快回复。再次感谢!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。