如何将最长9999位的任意进制数(最高36进制)转换为目标进制?
问题描述
需要处理长度可达9999位的超大数字,无法通过常规int类型存储;支持最高36进制,大于9的数字用大写字母A-Z依次表示。已编写初步C语言代码,但对核心的convert函数实现思路模糊,寻求实现指导。现有代码如下:
#include <stdio.h> #include <stdlib.h> #define LEN 1000 int exp(int expBase, int power) { unsigned int i = 1; int j; for (j = 0; j < power; j++) i *= expBase; return i; } void convert(char *num, int base1, int base2, int length) { char numC[LEN]; int i; } int getNum(char *num) { int i = 0; char c; while ((c = fgetc(stdin)) != ' ') { num[i] = c; i++; } return i; } int main() { char num[LEN]; int n, base1, base2, length; scanf("%d", &n); for (int i = 0; i < n; i++) { length = getNum(num); scanf("%d %d", &base1, &base2); convert(num, base1, base2, length); } return 0; }
注:代码为初版未测试,错误不影响核心需求,重点求实现思路。
实现思路与代码建议
核心逻辑
由于数字长度远超常规整型范围,必须用数组模拟大整数运算,推荐两种实现路径:
路径1:先转十进制大整数,再转目标进制
分两步完成转换,逻辑直观易调试:
步骤1:原进制字符转十进制大整数数组
- 先实现字符转数值的辅助函数:
int char_to_val(char c) { if (c >= '0' && c <= '9') return c - '0'; else if (c >= 'A' && c <= 'Z') return 10 + (c - 'A'); return -1; // 非法字符标记 } - 用数组存储十进制大整数(低位在前,方便后续除法操作):
- 初始化足够大的数组(如
int dec[10000] = {0};),记录有效长度dec_len。 - 遍历输入字符,对数组执行
dec = dec * base1 + 当前位数值,模拟大数乘法与加法:int dec[10000] = {0}; int dec_len = 0; // 初始化第一位 dec[dec_len++] = char_to_val(num[0]); for (int i = 1; i < length; i++) { int val = char_to_val(num[i]); int carry = 0; // 数组整体乘base1 for (int j = 0; j < dec_len; j++) { int temp = dec[j] * base1 + carry; dec[j] = temp % 10; carry = temp / 10; } // 处理乘法进位 while (carry > 0) { dec[dec_len++] = carry % 10; carry /= 10; } // 加上当前位数值 carry = val; int j = 0; while (carry > 0 && j < dec_len) { int temp = dec[j] + carry; dec[j] = temp % 10; carry = temp / 10; j++; } while (carry > 0) { dec[dec_len++] = carry % 10; carry /= 10; } }
- 初始化足够大的数组(如
步骤2:十进制大整数转目标进制
用除基取余法,不断将数组除以base2,收集余数后倒序输出:
- 实现数值转字符的辅助函数:
char val_to_char(int val) { if (val >= 0 && val <= 9) return '0' + val; else if (val >= 10 && val <= 35) return 'A' + (val - 10); return '?'; // 非法数值标记 } - 执行除基取余:
char result[10000]; int res_len = 0; while (dec_len > 0) { int remainder = 0; // 模拟大数除以base2,商保留在原数组 for (int j = dec_len - 1; j >= 0; j--) { int temp = remainder * 10 + dec[j]; dec[j] = temp / base2; remainder = temp % base2; } // 移除高位无效0 while (dec_len > 0 && dec[dec_len - 1] == 0) { dec_len--; } // 记录余数 result[res_len++] = val_to_char(remainder); } // 倒序输出结果 for (int i = res_len - 1; i >= 0; i--) { printf("%c", result[i]); } printf("\n");
路径2:直接对原进制数执行除基取余(更高效)
跳过中间十进制转换,直接对原进制数值数组执行除基取余,减少运算量:
- 先将输入字符转成原进制数值数组:
int src[10000]; int src_len = length; for (int i = 0; i < length; i++) { src[i] = char_to_val(num[i]); } - 循环执行除基取余:
char result[10000]; int res_len = 0; while (src_len > 0) { int remainder = 0; // 从高位到低位做除法 for (int i = 0; i < src_len; i++) { int temp = remainder * base1 + src[i]; src[i] = temp / base2; remainder = temp % base2; } // 移除高位无效0 while (src_len > 0 && src[0] == 0) { for (int i = 0; i < src_len - 1; i++) { src[i] = src[i + 1]; } src_len--; } result[res_len++] = val_to_char(remainder); } // 倒序输出结果 for (int i = res_len - 1; i >= 0; i--) { printf("%c", result[i]); } printf("\n");
原代码的修正建议
- 删除无用的
exp函数:该函数会因指数过大直接溢出,完全无法处理大数场景。 - 扩容长度限制:原
LEN=1000不足以存储9999位数字,建议改为#define MAX_LEN 10000。 - 修复
getNum函数:补充数组越界检查与字符串结束符,处理换行符场景:int getNum(char *num, int max_len) { int i = 0; char c; while ((c = fgetc(stdin)) != EOF && c != ' ' && c != '\n') { if (i < max_len - 1) { // 留一位存储字符串结束符 num[i++] = c; } } num[i] = '\0'; return i; }
内容的提问来源于stack exchange,提问作者Someone Someone
相关产品推荐
相关产品推荐

