问题C:进制转换
时间限制 | 内存限制 |
1.000sec | 32MB |
题目描述:
将一个长度最多为30位数字的十进制非负整数转换为二进制数输出。
输入:
多组数据,每行为一个长度不超过30位的十进制非负整数。(注意是10进制数字的个数可能有30个,而非30bits的整数 ,输入可能有多行)
输出:
每行输出对应的二进制数。
样例输入:
985
211
1126
样例输出:
1111011001
11010011
10001100110
分析:
首先我们知道:一般的整数的取值范围如下:
类型 | 取值范围 |
int && long | -2147483648 ~ +2147483647 |
long long | -9223372036854775808 ~ +9223372036854775807 |
1.对于无符号型的整数,在原有的正的取值范围基础上扩大一倍即可。因此我们没法直接用整形变量来储存题目中给的数据。所以在此我们采用 数组 的形式来储存数据(先用char 类型数组读入数据,然后将数据对应转换到int型数组中,然后处理int 型数组即可):
2.对于 int 型数组中的数据我们要怎么处理才能将其转变为二进制的呢?我们来看一个例子:
3.显然上图就是我们对于已知的十进制数字转换成二进制的过程,结果倒序输出:50对应的二进制数即为 110010;现在对于这道题目来说,我们将数值存在了数组中那么50在数组中的形式为:{5 , 0}。我们没法用直接除的方法来解决。但我们可以这样来思考:
3.1 因为我们十进制转二进制,对数值进行处理的过程大概如下:
50 % 2 = 0;然后将0记下,并将操作的数据除以2:50 / 2 = 25;
再:25 % 2 = 1;将1记下,将操作的数字除以2:25 / 2 = 12;
......
直到操作数等于0的时候停止,倒序输出记下的数就是我们求的二进制的数。
3.2 显然,在这个过程中,需要知道的数据就是我们的:操作数 、转换的进制数 、每一轮的余数 。因为被操作数每一轮发生一次变化,并且每次操作后就变小,所以,我们可以用原来操作数占用的数组空间来储存变化后的操作数(50 变为 25 再变为 12 …我们只需改变数组中的值即可),我们都用数组 num_int 来表示
3.3 要转换的进制数显然是2,那么每一轮的余数怎么算?。这里就需要回到我们小学三年级学的除法上了(竖式计算除法),哈哈:
3.3.1 我们要计算
12
9
10
129_{10}
12910 的二进制数:
首先:
取出最高项1作为被除数,除以二显然不够除,我们写0在商上面。
然后:
将2拉下来,这样我们的被除数就变为了1 × 10 + 2 = 12,接着用被除数除以2:12 ÷ 2 = 6,所以将6写在商0的后面。我们的商就变为了 06;被除数变为了 12 % 2 = 0;
最后:
将最后一项9拉下来作为被除数,被除数变为0 * 10 + 9 = 9,接着9/2 = 4;余下1,将4写在商的位置,我们的商就是064 , 余数是1;
我们得到:129 ÷ 2 = 64 ······ 1
我们下轮用到的就是商 64 ,对64 做相同的处理,那么余数1,会被记住 , 继续处理商64.....直到商变为0为止 , 按顺序记录下所有的余数,最后倒序输出所有的余数就是我们要的结果。
显然,我们可以看出,每次处理完一位数字后,我们都会用到上一次剩余的结果 temp_before, 并将 temp_before ×10 + 这次要处理的那一位数字 (上图的 1 × 10 + 2 和 0 × 10 + 9就是这个道理),现在我们就明白了:
处理int型数组中的数字,和小学除法一样,我们要先从最高位开始 逐位处理!
所以,我们需要一个整形变量,temp 从最高位开始来储存每一位上的数字,需要一个整型变量 temp_before 来储存上次操作后的(模除)结果,进行一下循环即可。
while((num_int数组非零)){
int temp_before = 0; //刚开始“上一步”剩余的数是0;
for(int i = 0 ; i < num_int数组的长度 ; i++){
int temp = (num_int[i] + 10 * temp_before);
num_int[i] = (num_int[i] + 10 * temp_before) / 2;
temp_before = temp % 2; //这一次模除的值(余数)留给下一次处理。
}
可以将余数temp_before储存到新整形数组中或者一个堆栈中。
数组中最后倒序输出,堆栈中最后出栈即可。
因为此题目中的 模除2 的余数,肯定只能取 0 或 1 ,所以两种方法都可以。
}
#include<bits/stdc++.h>
using namespace std;
int isEmpty(int num[] , int length){
for(int i = 0 ; i < length ; i++){
if(num[i] != 0)
return 0; //返回0代表有非零值。
}
return 1; //返回1代表所有的数据处理好了
}
int main(){
int result[200] , count = 0; //存放余数(结果),count 来计结果数目
int num_int[31]; //存放系统给出的数据
char num_char[31]; //接受输入数据
while(scanf("%s" , num_char) != EOF){
count = 0; //对于一个新数,count要清零。
int length = strlen(num_char); //存放输入的数字个数
for(int i = 0 ; i < length ; i++){
num_int[i] = num_char[i] - '0'; //将char类型的数据改为int类型的
}
if(isEmpty(num_int , length) == 1){
printf("0"); //对于输入全为0的处理,直接输出0就好
}
while(isEmpty(num_int , length) == 0){ //不全为空,就是没处理好 ,继续处理
int temp_before = 0; //刚开始“上一步”剩余的数是0;
for(int i = 0 ; i < length; i++){
int temp = (num_int[i] + 10 * temp_before);
num_int[i] = (num_int[i] + 10 * temp_before) / 2;
temp_before = temp % 2; //这一次模除的值(余数)留给下一次处理。
}
result[count++] = temp_before;
}
for(int i = count - 1 ; i > -1 ; i--){
printf("%d" , result[i]);
}
printf("\n");
}
}