查看: 9|回复: 0

从八进制到十六进制:大数转换的完整实现指南(洛谷B3617...

[复制链接]
  • TA的每日心情
    无聊
    昨天 10:41
  • 签到天数: 12 天

    [LV.3]偶尔看看II

    10

    主题

    0

    回帖

    37

    积分

    新手上路

    Rank: 1

    积分
    37
    发表于 昨天 10:46 | 显示全部楼层 |阅读模式
    一、问题背景
    洛谷B3617题目要求将一个可能非常大的八进制数转换为十六进制数。由于输入可能长达1000位,传统的数值类型无法存储这么大的数字,因此需要使用字符串处理技术来模拟大数运算
    二、完整代码实现
    1. #include <iostream>
    2. #include <string>
    3. #include <algorithm>
    4. using namespACe std;

    5. // 验证八进制字符串合法性
    6. bool isValidOctal(const string& s) {
    7.     if(s.empty() || s.length() > 1000) return false;
    8.     for(char c : s) {
    9.         if(c < '0' || c > '7') return false;
    10.     }
    11.     return true;
    12. }

    13. // 八进制转十进制(大数处理)
    14. string octalToDecimal(const string& octal) {
    15.     string decimal = "0";
    16.     for(char c : octal) {
    17.         int digit = c - '0';
    18.         // 十进制数乘以8
    19.         string temp = decimal;
    20.         int carry = 0;
    21.         for(int i = temp.length()-1; i >= 0; i--) {
    22.             int num = (temp[i] - '0') * 8 + carry;
    23.             temp[i] = (num % 10) + '0';
    24.             carry = num / 10;
    25.         }
    26.         if(carry > 0) {
    27.             temp.insert(0, 1, carry + '0');
    28.         }
    29.         // 加上当前位
    30.         carry = digit;
    31.         for(int i = temp.length()-1; i >= 0 && carry > 0; i--) {
    32.             int num = (temp[i] - '0') + carry;
    33.             temp[i] = (num % 10) + '0';
    34.             carry = num / 10;
    35.         }
    36.         if(carry > 0) {
    37.             temp.insert(0, 1, carry + '0');
    38.         }
    39.         decimal = temp;
    40.     }
    41.     return decimal;
    42. }

    43. // 十进制转十六进制(大数处理)
    44. string decimalToHex(const string& decimal) {
    45.     if(decimal == "0") return "0";
    46.    
    47.     string hex;
    48.     string num = decimal;
    49.     const string hexDigits = "0123456789abcdef";
    50.    
    51.     while(num != "0") {
    52.         int remainder = 0;
    53.         string temp;
    54.         // 模拟除法过程
    55.         for(char c : num) {
    56.             int digit = remainder * 10 + (c - '0');
    57.             remainder = digit % 16;
    58.             digit /= 16;
    59.             if(!temp.empty() || digit > 0) {
    60.                 temp.push_back(digit + '0');
    61.             }
    62.         }
    63.         hex.push_back(hexDigits[remainder]);
    64.         num = temp.empty() ? "0" : temp;
    65.     }
    66.    
    67.     reverse(hex.begin(), hex.end());
    68.     return hex;
    69. }

    70. int main() {
    71.     string octal;
    72.     cin >> octal;
    73.    
    74.     if(!isValidOctal(octal)) {
    75.         cout << "Invalid input: must be octal string (0-7) with length ≤1000" << endl;
    76.         return 1;
    77.     }
    78.    
    79.     string decimal = octalToDecimal(octal);
    80.     string hex = decimalToHex(decimal);
    81.    
    82.     cout << hex << endl;
    83.     return 0;
    84. }
    复制代码

    三、代码解析1. 输入验证
    isValidOctal函数检查输入字符串是否为空、长度是否超过1000,以及是否包含非八进制数字字符(0-7以外的字符)。
    2. 八进制转十进制
    octalToDecimal函数采用逐位处理的方式:
    • 初始化十进制结果为"0"
    • 对每个八进制数字:

      • 当前十进制结果乘以8(模拟大数乘法)
      • 加上当前位的值(模拟大数加法)

    • 使用进位机制处理运算过程中的溢出

    3. 十进制转十六进制
    decimalToHex函数采用除法取余法:
    • 不断将十进制数除以16,记录余数
    • 使用字符串模拟大数除法过程
    • 最后将余数序列反转得到正确顺序

    4. 主函数逻辑
    • 读取输入
    • 验证输入合法性
    • 先转换为十进制,再转换为十六进制
    • 输出结果

    四、学习要点
    • 大数处理技巧:使用字符串模拟数字运算
    • 进制转换原理:理解不同进制间的转换方法
    • 边界条件处理:特别是输入为"0"的情况
    • 字符串操作:插入、反转等常用字符串方法的应用

    五、性能优化建议
    • 可以预先分配足够大的字符串空间,减少内存分配次数
    • 考虑使用更高效的算法,如直接八进制转十六进制(跳过十进制中间步骤)
    • 对于特别大的输入,可以并行处理不同数位

    六、常见问题解答
    Q: 为什么需要先转十进制再转十六进制? A: 这是最直观的实现方式,虽然效率不是最高,但易于理解和实现。
    Q: 如何处理前导零? A: 当前代码已经正确处理,不会输出不必要的前导零。
    Q: 为什么结果中的字母是小写的? A: 题目通常不区分大小写,如需大写可以简单转换。

    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    快速回复 返回顶部 返回列表