前面的內容來源于:http://www.cnblogs.com/phinecos/archive/2009/09/11/1564975.html

引用原文:

在數據結構課關于棧的這一章中,我們都學過用2取余法來將一個10進制數轉換為一個二進制數,進而可以推廣到n取余法,經其轉換為n進制(n任意指定)。

確實,這是一個很基礎的題目,可你是否想過如果這個10進制數是一個大數(其位數可能上千位,此時用一般數據類型肯定是會溢出的),那么這個問題又如何來求解呢?

當然,也許你會說很簡單嘛,自己寫一個大數類(當然至少要寫一個大數除法才行),或者你用的是Java這種現代化語言,就更輕松了,直接用BigInteger這樣的大數類就可以來表示一個大數,進而用書上教的方法來實現。

但是,真的需要用到大數類嗎?事實上,殺雞焉用牛刀,我們在紙上模擬一番上述運算后就可以發現,只要做一些小小的改進,就可以在不使用大數的情況下,也可以通過n取余的原理來實現大數的進制轉換的。(當然,整體的思想仍然是n取余原理!?。。?/span>

舉個簡單的例子,就比如說把10進制數12轉換為2進制形式,書上的方法可以用下圖來表示

按照先余為低位,后余為高位這條鐵律,其結果為1100.

這是書上教我們的常規思路(可惜按這個的話,大數是沒法考慮的,因為假如這里不是12,而是一個1000位的大數,由于是是對大數的整體進行取余運算,不使用大數類及其除法操作,又如何得以進行呢?),可我們的目的是不使用大數類,那么現在我們就來換一個視角來看這個問題,12是一個十位數,十位上是1,個位上是2,按照我們正常的思維來看,這個計算應該是下面這樣的:


那么我們發現在第一輪運算時,十位上的1作為被除數,2作為除數,得到的商是0,余數是1(可以斷言只考慮當前這一個數位的計算,余數或是0,或是1,若是1的話,則進入下一數位(這里即對個位進行運算)時,要用1乘上進制(這里是10)再加上下一個數位上的值(這里是2),即得到運算進入個位時被除數是12,除數是2,得到的商是6,余數是0。第一輪運算的結果是商是06,余數是0.

進入第二輪運算,則上一輪的商6(這里首先要去掉前面多余的0)變成本輪的被除數,如此下去,即可得到每輪的余數。

推廣開來,如果被除數是一個1000位的大數,例如“12343435154324123……342314324343”

那么我們照樣可以從第一個數位開始逐位考慮,比如第一位是1(作為被除數),2是除數,得到的商是0,余數是1,然后是第二個數位2,由于上一位留下了余數1,則此時被除數應該是1*10+2 = 12,所以得到的商是6,余數是0,即運算到此時的商是06,然后是第三個數位3,由于上一個數位留下的余數是0,所以此時被除數就是3,。。。如此下去就完成第一輪的運算,

這一輪完畢后,需要把得到的商變成下一輪的被除數,繼續上述的運算,直到被除數為0才停止。

下面給出了一個示例代碼,展示了如何將一個10進制的大數轉換為其二進制形式,僅供參考:

#include <stdio.h>
#include
<string.h>

char str[1000];//輸入字符串
int start[1000],ans[1000],res[1000]; //被除數,商,余數

//轉換前后的進制
const int oldBase = 10;
const int newBase = 2;

void change()
{
//各個數位還原為數字形式
int i,len = strlen(str);
start[
0] = len;
for(i=1;i<= len;i++)
{
if(str[i-1] >= '0' && str[i-1] <= '9')
{
start[i]
= str[i-1] - '0';
}
}
}

void solve()
{
memset(res,
0,sizeof(res));//余數初始化為空
int y,i,j;
//模n取余法,(總體規律是先余為低位,后余為高位)
while(start[0] >= 1)
{
//只要被除數仍然大于等于1,那就繼續“模2取余”
y=0;
i
=1;
ans[
0]=start[0];
//
while(i <= start[0])
{
y
= y * oldBase + start[i];
ans[i
++] = y/newBase;
y
%= newBase;
}
res[
++res[0]] = y;//這一輪運算得到的余數
i = 1;
//找到下一輪商的起始處
while((i<=ans[0]) && (ans[i]==0)) i++;
//清除這一輪使用的被除數
memset(start,0,sizeof(start));
//本輪得到的商變為下一輪的被除數
for(j = i;j <= ans[0];j++)
start[
++start[0]] = ans[j];
memset(ans,
0,sizeof(ans)); //清除這一輪的商,為下一輪運算做準備
}
}

void output()
{
//從高位到低位逆序輸出
int i;
for(i = res[0];i >= 1;--i)
{
printf(
"%d",res[i]);
}
printf(
"\n");
}

int main()
{
scanf(
"%s",str);
change();
solve();
output();
return 0;
}

個人根據POJ1220,總結高精度的N進制轉換模板如下:

/*
高精度進制轉換
把oldBase 進制的數轉化為newBase 進制的數輸出。
調用方法,輸入str, oldBase newBase.
change();
solve();
output();
也可以修改output(),使符合要求,或者存入另外一個字符數組,備用
*/
#include
<stdio.h>
#include
<string.h>
#defien MAXSIZE
1000
char str[MAXSIZE];//輸入字符串
int start[MAXSIZE],ans[MAXSIZE],res[MAXSIZE];//被除數,商,余數
int oleBasw,newBase;//轉換前后的進制

//單個字符得到數字
int getNum(char c)//這里進制字符是先數字,后大寫字母,后小寫字母的
{
if(c>='0'&&c<='9') return c-'0';//數字
if(c>='A'&&c>='Z') return c-'A'+10;//大寫字母
return c-'a'+36;//小寫字母
}
//數字得到字符
char getChar(int i)
{
if(i>=0&&i<=9)return i+'0';
if(i>=10&&i<=35)return i-'10'+'A';
return i-36+'a';
}
void change()//把輸入的字符串的各個數位還原為數字形式
{
int i;
start[
0]=strlen(str);//數組的0位存的是數組長度
for(i=1;i<=start[0];i++)
start[i]
=getNum(str[i-1]);
}
void solve()
{
memset(res,
0,sizeof(res));//余數位初始化為空
int y,i,j;
while(start[0]>=1)
{
y
=0;i=1;
ans[
0]=start[0];
while(i<=start[0])
{
y
=y*oldBase+start[i];
ans[i
++]=y/newBase;
y
%=newBase;
}
res[
++res[0]]=y;//這一輪得到的余數
i=1;//找下一輪商的起始處,去掉前面的0
while(i<=ans[0]&&ans[i]==0) i++;
memset(start,
0,sizeof(start));
for(j=i;j<ans[0];j++)
start[
++start[0]]=ans[j];
memset(ans,
0,sizeof(ans));
}
}
void output()//從高位到低位逆序輸出
{
int i;
for(i=res[0];i>=1;i--)
printf(
"%d",getChar(res[i]));
printf(
"\n");
}