Codeup小白掉坑经验总结之 进制转换 id=1943 1950

  • 题目如下
    1943: 进制转换
    时间限制: 1 Sec 内存限制: 32 MB

题目描述
将一个长度最多为30位数字的十进制非负整数转换为二进制数输出。

输入
多组数据,每行为一个长度不超过30位的十进制非负整数。
(注意是10进制数字的个数可能有30个,而非30bits的整数)

输出
每行输出对应的二进制数。

样例输入
985
211
1126
样例输出
1111011001
11010011
10001100110

这题。。。嗯。。。不是坑,是自己实在想不出怎么实现,于是纯粹学习大神的代码,然后理解,对于我来说,能理解就已经成功了。

这是我略加修改的代码:

#include<cstdio>  
#include<cstring>
int main()
{
char m[1000];
int i,a[1000],n[1000];
while(~scanf("%s",m))
{
int k=strlen(m),len=strlen(m),num=0;
while(len>0)
{
n[num++]=(m[k-1]-'0')%2;
int c=0;
for(i=0;i<k;i++)
{
int s=((m[i]-'0')+10*c)/2;
c=(m[i]-'0')%2;
m[i]=s+'0';
}
while(m[k-len]=='0')
len--;
}
for(i=num-1; i>=0; i--)
printf("%d",n[i]);
printf("\n");
}
return 0;
}

本文仅作解读,为自己积累经验,以及为遇到同样问题的同学提供微薄的帮助,不做其他用途。

首先,这道题目规定了输入的十进制整数可能达到30位之多,想想,int型表示的最大数是1e10级 long long型最多也只能表示1e19级别的数,而这题的数量级是1e30级别,想用整数除整取余的思想是不可能了= =、、

所以,这题只能采用字符串与整型之间的转换,对整个字符串进行除2取余的操作,然后一次一次的除,最终得到完整的二进制表示。

关键就在于这个整体除2取余的操作,第一次看到这个代码的时候根本不知道这是在干嘛,只有自己拿例子一点一点模拟,最终才找到规律。

关键代码就是这部分

for(i=0;i<k;i++)
{
int s=((m[i]-'0')+10*c)/2;
c=(m[i]-'0')%2;
m[i]=s+'0';
}

m[]是输入的字符串,从i=0开始即从数字的最高位开始,这和平时做两个数字相除的方式是一样的,m[i]-‘0’,是将字符‘0’~‘9’转换成数字0~9,然后c是上一位留下来的余数(这个写写平时的除法过程就懂了~)。

刚开始c肯定设为0,因为上一位没有余下来的数嘛,然后s=((m[i]-‘0’)+10*c)/2;就是对(这一位数+上一位的余数×进制10)再除2取整,然后把c赋值为余数用于下一位的运算,就这样一直除到最后一位,这样就完成了一次除2的运算。

通过 n[num++]=(m[k-1]-‘0’)%2; 将每次运算过后的结果的最低位取余,放入最终的结果数组的相应位置,通过一次又一次的循环,就能得到最后的结果,然后输出,就可以啦。

循环判断跳出条件,就是从最高位判断是否为0,为0,len变量就减一,这也和平时的计算规则相同,最终判断到最低位都是0,那么就可以跳出循环。

这题的while(~scanf(“%s”,m))写法也让我很惊奇,原来我都是这样写的while(scanf(“%s”,m)!=EOF),然后我就去翻了一下scanf函数的定义,当scanf函数读入变量时,返回值为成功读入参数的个数,但是读到EOF,即出现了无法读取的现象,此时会返回-1,而~是位运算中的取反,-1的机器码是111111111111111(管它有几个,就是全是1( ‵▽′)ψ),取反之后正好全为0,就会跳出while循环,而返回值只要不是-1,那么位取反之后都不会为0,所以就会一直进行~

整理完毕~又学习到了不少新知识(๑•̀ㅂ•́)و✧

2018.1.22补充 题目 id=1950 进制转换终极版!

题目如下

1950:进制转换
时间限制: 1 Sec 内存限制: 32 MB

题目描述
将M进制的数X转换为N进制的数输出。

输入
输入的第一行包括两个整数:M和N(2<=M,N<=36)。
下面的一行输入一个数X,X是M进制的数,现在要求你将M进制的数X转换成N进制的数输出。

输出
输出X的N进制表示的数。

样例输入
10 2
11
样例输出
1011
提示
注意输入时如有字母,则字母为大写,输出时如有字母,则字母为小写。

同样是利用上面的思想,把10进制换成M,把2进制换成N,就可以啦,原理相同不再赘述,下面奉上代码~
这样就可以实现任意长整数在键盘可表示范围内的任意进制的转换了~

#include <cstdio>
#include <cstring>
struct bign
{
int d[1000];
int len;
bign()
{
memset(d,0,sizeof(d));
len=0;
}
};
bign change(char s[])
{
bign a;
a.len=strlen(s);
for(int i=0;i<a.len;i++)
{
if(s[a.len-i-1]>='0'&&s[a.len-i-1]<='9')
a.d[i]=s[a.len-i-1]-'0';
else if(s[a.len-i-1]>='A'&&s[a.len-i-1]<='Z')
a.d[i]=s[a.len-i-1]-'A'+10;
}
return a;
}
int main()
{
int m,n;
while(~scanf("%d %d",&n,&m))
{
char a[1000]={'\0'};
char out[1000]={'\0'};
scanf("%s",a);
bign b=change(a);
int k=b.len,len=b.len,num=0;
while(len>0)
{
int c=0;
for(int i=len-1;i>=0;i--)
{
int s=(b.d[i]+n*c)/m;
c=(b.d[i]+n*c)%m;
b.d[i]=s;
}
if(c>=0&&c<=9)
out[num++]=c+'0';
if(c>=10&&c<=36)
out[num++]=c+'a'-10;
while(b.d[len-1]==0)
len--;
}
for(int i=num-1;i>=0;i--)
{
printf("%c",out[i]);
}
printf("\n");
}
return 0;
}