十进制与其他进制的转换——C++双精度版本

本文提供了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;
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Silencer76

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值