題目
題目描述
將一個長度最多爲30位數字的十進制非負整數轉換爲二進制數輸出。
輸入
多組數據,每行爲一個長度不超過30位的十進制非負整數。
(注意是10進制數字的個數可能有30個,而非30bits的整數)
輸出
每行輸出對應的二進制數。
樣例輸入
985
211
1126
樣例輸出
1111011001
11010011
10001100110
思路
10進制轉2進制就是,除2取餘;再用商除2取餘,一直到被除數(商)爲0,餘數的逆序就是該2進制數。
因爲是大數,所以被除數,商和餘數都要用數組存數。
輾轉取餘:一開始輸入的就是被除數,後來每一次求得的商爲被除數,一直循環直到被除數的數位爲0(即被除數爲0)
- 每一次大數取餘的過程:
從最高位開始除直到所有數位都除2了:
1) 這一位的被除數是上一位的餘數10(10進制)+這一位數:c = coldbase + start[i] - ‘0’;
2) 這一位商爲ans[i] = c / newbase + ‘0’;//這位商
3)這一位餘數位c = c%newbase;
- 最後一個餘數纔是大數除2的真正餘數
- 把大數商拷貝爲新的被除數,若商的最高位爲1的話被除數位數-1;拷貝時也從第2個元素開始拷貝即可
while (lennum){
//每輾轉除2一次商就要清零一次
memset(ans, 0, sizeof(ans));//初始化,否則無空間
c = 0;//一開始的上一位商爲0
for (int i = 0; i<lennum; i++){//從最高位開始運算,一次掃描全部並輾轉除2的過程
c = c*oldbase + start[i] - '0';
ans[i] = c / newbase + '0';//這位商
c = c%newbase;//這位餘
}
if (ans[0] == '0'){
head = 1;
lennum--;//最高位爲0,被除數位數減一個
}
else
head = 0;
res[lenres++] = c+'0';
strcpy(start, ans+head);//最高位若爲0則跳過
}
注意
- 要在合適的地方用memset給被除數,商和餘數都初始化,否則會出現分配空間異常或保留了上一輪數據等異常情況
- 被除數和商的存數都是隊列存儲;但是餘數爲了存儲方便用了棧存儲,輸出時要從lenres-1開始輸出喔
- 輸入的數最高位可能是多個0,把讀取的大數高位前的0都消掉再填入start被除數中 ,並讓總數位減去最高位那串0的數量
AC代碼
//大數除法
//用“模2取餘法”來將一個10進制數轉換爲一個二進制數,進而可以推廣到“模n取餘法”,經其轉換爲n進制(n任意指定)。
#include<bits/stdc++.h>
using namespace std;
int main()
{
//把讀取的大數高位前的0都消掉再填入start被除數中
char str[1000];
char start[1000], ans[1000], res[1000];//被除數,商,餘數
int lennum, c;//總數位,除數暫存數(上一位的餘(c)*oldbase(這裏是10)+這一位數)
int oldbase = 10, newbase = 2, head,lenres;//10進制,2進制 ,最高位 ,餘數總數位
while (scanf("%s", str) != EOF){
lennum=strlen(str);
for(int i=0;i<lennum;i++){
if(str[i]!='0'||i==(lennum-1)){
strcpy(start,str+i);
lennum-=i;//總數位減去最高位的那串0的數量
break;
}
}
lenres = 0;
memset(res, 0, sizeof(res));//初始化,否則無空間
while (lennum){
//每輾轉除2一次商就要清零一次
memset(ans, 0, sizeof(ans));//初始化,否則無空間
c = 0;//一開始的上一位商爲0
for (int i = 0; i<lennum; i++){//從最高位開始運算,一次掃描全部並輾轉除2的過程
c = c*oldbase + start[i] - '0';
ans[i] = c / newbase + '0';//這位商
c = c%newbase;//這位餘
}
if (ans[0] == '0'){
head = 1;
lennum--;//最高位爲0,被除數位數減一個
}
else
head = 0;
res[lenres++] = c+'0';
strcpy(start, ans+head);//最高位若爲0則跳過
}
for (int i = lenres - 1; i >= 0; i--)
printf("%c", res[i]);
printf("\n") ;
memset(start, 0, sizeof(start));//初始化
}
return 0;
}
延伸爲a進制轉爲b進制
每一位的暫存數被除數c = c*oldbase + a_ten(start[i]);
int a_ten(char x){
if (isdigit(x))
return x - '0';
switch (x){
case 'a':return 10;
case 'A':return 10;
case 'b':return 11;
case 'B':return 11;
case 'c':return 12;
case 'C':return 12;
case 'd':return 13;
case 'D':return 13;
case 'e':return 14;
case 'E':return 14;
case 'f':return 15;
case 'F':return 15;
}
}
每一位的商ans[i] = ten_a(c / newbase);
和每一位保留的餘數res[lenres++] = ten_a©;
char ten_a(int x){
if (x >= 0 && x <= 9)
return x + '0';
switch (x)
{
case 10: return 'A';
case 11: return 'B';
case 12: return 'C';
case 13: return 'D';
case 14: return 'E';
case 15: return 'F';
}
}
AC代碼
注意:輸出0要特判
//大數除法
//用“模2取餘法”來將一個10進制數轉換爲一個二進制數,進而可以推廣到“模n取餘法”,經其轉換爲n進制(n任意指定)。
#include<stdio.h>
#include<stdlib.h>
#include<string>
using namespace std;
int a_ten(char x){
if (isdigit(x))
return x - '0';
switch (x){
case 'a':return 10;
case 'A':return 10;
case 'b':return 11;
case 'B':return 11;
case 'c':return 12;
case 'C':return 12;
case 'd':return 13;
case 'D':return 13;
case 'e':return 14;
case 'E':return 14;
case 'f':return 15;
case 'F':return 15;
}
}
char ten_a(int x){
if (x >= 0 && x <= 9)
return x + '0';
switch (x)
{
case 10: return 'A';
case 11: return 'B';
case 12: return 'C';
case 13: return 'D';
case 14: return 'E';
case 15: return 'F';
}
}
int main()
{
//把讀取的大數高位前的0都消掉再填入start被除數中
char str[1000];
char t[100];
char start[1000], ans[1000], res[1000],tt;//被除數,商,餘數,暫存數
int lennum, c;//總數位,除數暫存數(上一位的餘(c)*oldbase(這裏是10)+這一位數)
int oldbase, newbase, head,lenres;//old進制,new進制 ,最高位 ,餘數總數位
while (scanf("%s", str) != EOF){
lennum = strlen(str);
for (int i = 0; i<lennum; i++){
if (str[i] != '0' || i == (lennum - 1)){
strcpy(start, str + i);
lennum -= i;//總數位減去最高位的那串0的數量
break;
}
}
printf("old/new進制:");
scanf("%d %d", &oldbase, &newbase);
lenres = 0;
memset(res, 0, sizeof(res));//初始化,否則無空間
while (lennum){
//每輾轉除2一次商就要清零一次
memset(ans, 0, sizeof(ans));//初始化,否則無空間
c = 0;//一開始的上一位商爲0
for (int i = 0; i<lennum; i++){//從最高位開始運算,一次掃描全部並輾轉除2的過程
c = c*oldbase + a_ten(start[i]);
ans[i] = ten_a(c / newbase);//這位商
c = c%newbase;//這位餘
}
if (ans[0] == '0'){
head = 1;
lennum--;//最高位爲0,被除數位數減一個
}
else
head = 0;
res[lenres++] = ten_a(c);
strcpy(start, ans+head);//最高位若爲0則跳過
}
if (lenres == 1)//如果餘數只有一位那麼直接輸出,否則0就被跳過什麼都沒有了
printf("%c", res[0]);
else
for (int i = lenres - 1; i >= 0; i--){
tt = res[i];
if (tt == '0'&&i == (lenres - 1))//首位的0都跳過不輸出
lenres--;
else
printf("%c", tt);
}
printf("\n");
memset(start, 0, sizeof(start));//初始化
}
system("PAUSE");
return 0;
}