题目1: 10 进制转 x 进制
题目2: x 进制转 10 进制
题号1:B3619
题号2:B3620
难度:普及一
题目1分析
首先就需要万能的除基取余法
这个一定要掌握,该方法代码如下
int zhuan(long long num,int k)
{
int n=0;
while(num>0)
{
if(num % k < 10)
a[n++] = (num % k)+'0';
else
a[n++] = (num % k)-10 + 'A';
num /= k;
}
n--;
return n;
}
这个是我最喜欢用的形式,形参是传入的长整型十进制数,和一个进制。返回值是具体多少位。
如果仔细看你会发现,这个函数虽然转换了进制,但是它是典型的会将得到的进制数反着来,但是,为什么我不在函数里面将之反过来,而是仅仅返回一个位数呢。
答案是:反着输出,或者反着应用就可以。
n = zhuan(x,k);
for(int i=n;i>=0;i--)
printf("%c",a[i]);
整体来看一下代码:
源代码
#include<stdio.h>
#include<math.h>
char a[1000];
int zhuan(long long num,int k)
{
int n=0;
while(num>0)
{
if(num % k < 10)
a[n++] = (num % k)+'0';
else
a[n++] = (num % k)-10 + 'A';
num /= k;
}
n--;
return n;
}
int main()
{int n = 0,k;
long long x;
scanf("%lld %d",&x,&k);
n = zhuan(x,k);
for(int i=n;i>=0;i--)
printf("%c",a[i]);
return 0;
}
特别简便清晰,也不用我过多解释了,通过也是嘎嘎块。
关于类似的题还有反过来的进制转化为十进制类型,在这简单提一下,同样也是只需要掌握一种基本转化算法就够用,我推荐中学阶段常用的权重次方累加法,看题
题目2分析
只需要理解 3541(8) -> 1*8^0 + 4*8^1+5*8^2+3*8^3
通常传入的是字符串,因为要储存高进制数,则就需要注意字符 到 数值 的转换
f (s[i] >= '0' && s[i] <= '9') {
digit = s[i] - '0';
} else {
digit = s[i] - 'A' + 10;
}
if (digit >= x) { // 非法字符检查
printf("0\n");
return 0;
}
然后就是累加阶段
dec += digit * (long long)pow(x, i);
话不多说上代码
#include <stdio.h>
#include <string.h>
#include <math.h>
int main() {
int x;
char s[20];
scanf("%d\n%s", &x, s);
int len = strlen(s);
long long dec = 0;
// 反转字符串,从低位开始处理
for (int i = 0; i < len / 2; i++) {
char temp = s[i];
s[i] = s[len - 1 - i];
s[len - 1 - i] = temp;
}
for (int i = 0; i < len; i++) {
int digit;
if (s[i] >= '0' && s[i] <= '9') {
digit = s[i] - '0';
} else {
digit = s[i] - 'A' + 10;
}
if (digit >= x) {
printf("0\n");
return 0;
}
dec += digit * (long long)pow(x, i);
}
printf("%lld\n", dec);
return 0;
}
关于进制之间的转换其实还有很多方法,但是基础的除基取余法基本上就够用。
算法知识拓展
数组存储余数(高效处理大数)
优化点:
使用数组存储余数,避免频繁的字符串操作,适合处理大数
void decToBase(long long num, int base, char *result) {
if (num == 0) {
strcpy(result, "0");
return;
}
int i = 0, isNegative = 0;
if (num < 0) {
isNegative = 1;
num = -num;
}
char digits[200]; // 足够存储大数
while (num > 0) {
long long rem = num % base;
digits[i++] = (rem < 10) ? (rem + '0') : (rem - 10 + 'A');
num /= base;
}
if (isNegative) digits[i++] = '-';
digits[i] = '\0';
// 反转并复制到结果
strcpy(result, strrev(digits));
}
递归实现(代码简洁)
原理:
递归调用自身处理高位余数,最终拼接结果。
void decToBaseRecursive(int num, int base, char *result, int *index) {
if (num == 0) return;
int rem = num % base;
decToBaseRecursive(num / base, base, result, index);
result[(*index)++] = (rem < 10) ? (rem + '0') : (rem - 10 + 'A');
}
void decToBase(int num, int base, char *result) {
if (num == 0) {
strcpy(result, "0");
return;
}
int index = 0;
if (num < 0) {
result[index++] = '-';
num = -num;
}
decToBaseRecursive(num, base, result, &index);
result[index] = '\0';
}
位运算优化(高效处理二进制 / 十六进制)
原理:
利用位运算快速提取每一位的值,适合二进制、十六进制等 2 的幂次进制。
void decToBinary(int num, char *result) {
if (num == 0) {
strcpy(result, "0");
return;
}
int i = 0, isNegative = 0;
if (num < 0) {
isNegative = 1;
num = -num;
}
while (num > 0) {
result[i++] = (num & 1) ? '1' : '0';
num >>= 1;
}
if (isNegative) result[i++] = '-';
result[i] = '\0';
strrev(result);
}
使用库函数(最简方案)
原理:
利用 sprintf
或 snprintf
直接格式化输出进制字符串。
void decToBase(int num, int base, char *result) {
if (base == 2) {
snprintf(result, 33, "%s%b", (num < 0) ? "-" : "", num);
} else if (base == 8) {
snprintf(result, 12, "%s%o", (num < 0) ? "-" : "", num);
} else if (base == 16) {
snprintf(result, 11, "%s%X", (num < 0) ? "-" : "", num);
} else {
strcpy(result, "不支持的进制");
}
}