本文提供了C++实现的进制转换代码,十进制下的数据存储格式为 double,其他进制下的数据存储格式为 string。整数部分的转换使用了栈,小数部分的转换使用了队列,栈和队列以链表的形式实现,没有用到任何STL库的内容。C-Free4.0及Visual C++6.0均可使用。
#include <iostream>
#include <iomanip>
#include <string>
#include <cmath>
using namespace std;
// 栈的基本操作
// 用于整数部分的转换
typedef struct Node1{
char data; // 存储数据
struct Node1 *next; // 递归定义
}Stack;
void InitStack(Stack *&S)
{ // 初始化
S=new Stack; // 赋予空间
S->next=NULL; // 设置为 NULL
}
bool IsEmptyStack(Stack *S)
{ // 判断是否为空栈
return S->next==NULL;
}
void Push(Stack *&S,char temp)
{ // 入栈
Stack *t=new Stack; // 赋予空间
t->data=temp; // 存储数据
t->next=S->next; // 更改节点顺序
S->next=t;
}
bool Pop(Stack *&S,char &temp)
{ // 出栈
if(S->next==NULL) // 如果为空栈
return false;
else
{
Stack *t=S->next;
temp=t->data; // 取出数据
S->next=t->next; // 更改节点顺序
delete t; // 删除该节点
return true;
}
}
void DestroyStack(Stack *&S)
{ // 销毁单链表
Stack *p=S; // 指向头节点
while(p!=NULL)
{
Stack *t=p->next; // 用临时指针存储 p->next 的节点
delete p; // 删除 p 节点
p=t; // 进行间接的 p=p->next
}
}
// 队列的基本操作
// 用于小数部分的转换
typedef struct Node2{
char data; // 存储数据
struct Node2 *next; // 递归定义
}Queue; // 循环队列
void InitQueue(Queue *&Q)
{ // 初始化循环队列
Q=NULL;
}
void EnQueue(Queue *&Q,char temp)
{ // 入队
Queue *s=new Queue; // 赋予空间
s->data=temp; // 存储数据
if(Q==NULL) // 如果队列为空
{
s->next=s; // 自己指向自己
Q=s; // 然后令指针指向该节点
}
else // 如果队列不为空
{
s->next=Q->next; // 更改节点顺序
Q->next=s;
Q=s; // 位移
}
}
bool DeQueue(Queue *&Q,char &temp)
{ // 出队
if(Q==NULL) // 如果队列为空
return false; // 就没有元素可以出队
else if(Q->next==Q) // 如果只有一个节点
{
temp=Q->data; // 取出数据
delete Q; // 删除节点
Q=NULL; // 重置为 NULL
return true;
}
else
{
Queue *t=Q->next; // 用临时指针指向队头
temp=t->data; // 取出数据
Q->next=t->next; // 更改节点顺序
delete t; // 删除节点
return true;
}
}
void DestroyQueue(Queue *&Q)
{ // 销毁队列
if(Q!=NULL)
{
Queue *p=Q->next;
while(p!=Q)
{
Queue *t=p->next;
delete p;
p=t;
}
delete Q;
Q=NULL;
}
}
// 十进制转换为其他进制
bool DTN_Round(int base,int radix,string &result)
{ // 十进制 转换为 其他进制 (整数部分)
if(radix<2||radix>36) // 进制非法
return false;
else
{
Stack *p;
char temp;
string sum=""; // 构造一个新 string
InitStack(p);
if(base<0) // 如果是负数,需要转换为正数进行计算
{
sum+='-'; // 在结果前面加上负号
base*=-1; // 转换为正数
}
if(base==0) // 如果本身为 0
Push(p,0); // 需要特判
for(;base!=0;base/=radix) // 一直除以进制
Push(p,char(base%radix)); // 并且进栈
while(Pop(p,temp)) // 一直出栈
{
temp+=48; // 此时数字 0~9 已经转换为字符 0~9
if(int(temp)>57) // 大于10的数字需要转换为大写字母
temp+=7;
sum+=temp; // string类可以直接连接
} // 所以 C++ 就很爽
result=sum; // 把结果转移给 result,传递回主函数
DestroyStack(p);
return true;
}
}
bool DTN_Decimal(double base,int radix,string &result)
{ // 十进制 转换为 其他进制 (小数部分)
if(radix<2||radix>36) // 进制非法
return false;
else
{
Queue *p;
char temp;
int i;
string sum=""; // 构造一个新 string
InitQueue(p);
if(base<0) // 如果是负数,需要转换为正数进行计算
{
sum+='-'; // 在结果前面加上负号
base*=-1; // 转换为正数
}
if(base!=0)
sum+='.';
for(i=0;i<8&&base!=0;i++) // 只取八位小数
{
base*=radix; // 乘以新进制
int x=int(base); // 取它的整数位
EnQueue(p,(char)x); // 入队
base-=x; // 去掉整数位
}
while(DeQueue(p,temp)) // 一直出队
{
temp+=48; // 此时数字 0~9 已经转换为字符 0~9
if(int(temp)>57) // 大于10的数字需要转换为大写字母
temp+=7;
sum+=temp; // string类可以直接连接
} // 所以 C++ 就很爽
result=sum; // 把结果转移给 result,传递回主函数
DestroyQueue(p);
return true;
}
}
bool DTN(double base,int radix,string &result)
{ // 十进制 转换为 其他进制 (对上面函数进行调用)
if(radix<2||radix>36) // 进制非法
return false;
else
{
string temp="";
if(base<0)
result='-';
else
result="";
base=fabs(base);
int x=int(base);
double z=base-(double)x;
DTN_Round(x,radix,temp);
result+=temp;
DTN_Decimal(z,radix,temp);
result+=temp;
return true;
}
}
// 其他进制转换为十进制
bool NTD_Round(string base,int radix,int &result)
{ // 其他进制 转换为 十进制 (整数部分)
if(radix<2||radix>36) // 进制非法
return false;
else
{
Stack *p;
int i=0,j=1,n=base.length(),sum=0;
char temp; // 用 str.length() 求 string类的长度
bool flag=false;
InitStack(p);
if(base[0]=='-') // 如果是负数
{
flag=true; // 更改 flag
i++;
}
for(;i<n;i++) // 逐个进栈
Push(p,base[i]);
while(Pop(p,temp)) // 逐个出栈
{
if(int(temp)>57) // 先处理字母
temp-=7;
temp-=48; // 转换为数字
sum+=int(temp)*j; // 数字 x 位权
j*=radix; // 位权更新
}
if(flag) // 如果 flag 为真
sum*=-1; // 把结果转换为负数
result=sum; // 把结果转移给 result,传递回主函数
DestroyStack(p);
return true;
}
}
bool NTD_Decimal(string base,int radix,double &result)
{ // 其他进制 转换为 十进制 (小数部分)
if(radix<2||radix>36) // 进制非法
return false;
else
{
Queue *p;
int i=0,n=base.length();
double j=1.0/radix,sum=0;
char temp; // 用 str.length() 求 string类的长度
bool flag=false;
InitQueue(p);
if(base[0]=='-') // 如果是负数
{
flag=true; // 更改 flag
i++;
}
if(n>13) // 太多位就不要了
n=13;
for(;i<n;i++) // 逐个入队
EnQueue(p,base[i]);
while(DeQueue(p,temp)) // 逐个出队
{
if(int(temp)>57) // 先处理字母
temp-=7;
temp-=48; // 转换为数字
sum+=int(temp)*j; // 数字 x 位权
j/=radix; // 位权更新
}
if(flag) // 如果 flag 为真
sum*=-1; // 把结果转换为负数
result=sum; // 把结果转移给 result,传递回主函数
DestroyQueue(p);
return true;
}
}
bool NTD(string base,int radix,double &result)
{ // 其他进制转换为十进制 (对上面函数进行调用)
if(radix<2||radix>36) // 进制非法
return false;
else
{
bool flag=false;
if(base[0]=='-')
{
flag=true;
base=base.substr(1);
}
int x=0,pos=base.find('.');
double temp=0;
if(pos==-1)
NTD_Round(base,radix,x);
else
{
string zs=base.substr(0,pos);
string xs=base.substr(pos+1);
NTD_Round(zs,radix,x);
NTD_Decimal(xs,radix,temp);
}
result=temp+(double)x;
if(flag)
result*=-1;
return true;
}
}
int main(void)
{
int j;
double z;
string b;
cout<<endl<<"------第一部分:十进制转换为其他进制------"<<endl;
cout<<endl<<"请输入 数字 以及 对应的进制:";
cin>>z>>j;
if(!DTN(z,j,b))
cout<<"进制范围非法";
else
cout<<"成功转换为 "<<j<<"进制,结果为:"<<b<<endl;
cout<<endl<<"------第二部分:其他进制转换为十进制------"<<endl;
cout<<endl<<"请输入 数字 以及 对应的进制:";
cin>>b>>j;
if(!NTD(b,j,z))
cout<<"进制范围非法";
else
cout<<"成功转换为 十进制,结果为:"<<setprecision(16)<<z<<endl;
cout<<endl;
return 0;
}