C语言整数进制转换,以及有理数进制转换的实现

       在实现进制转换前,我们要先了解进制转换的算法原理,以十进制转二进制为例:所采用的方法是“除二取余,逆序输出”,所以要借助栈进行逆序输出。而对于含有小数的有理数来说,整数部分仍遵循“除二取余,逆序输出”的规则,但小数部分的进制转换的算法不同,为“乘二取整,正序输出”的规则,由于是正序输出,所以不用借助栈,通过简单的循环语句也可打印输出。   

       当对整数进行进制转换时,对待转换的数先判断正负,通过if...else...算法分别实现正数和负数的转化(全部转化为正整数),转换的思想利用了算数运算中的取余和取整操作,借助栈先进后出的操作,进行辗转相除来实现。

#include<stdio.h>
#include<conio.h>
#include<stdlib.h>

typedef int datatype;
typedef struct node
{
	datatype data;
	struct node *next;
}*linkstack;

/*入栈*/
int Push(linkstack *top, datatype x)
{
	linkstack s = (linkstack)malloc(sizeof(struct node));
	if (s == NULL)
		return 0;
	s->data = x;
	s->next = (*top);
	(*top) = s;
	return 1;
}

/*判空*/
int Empty(linkstack top)
{
	if (top == NULL)
		return 1;
	return 0;
}

/*出栈*/
int Pop(linkstack*top, datatype*x)
{
	if (top != NULL)
	{
		linkstack p = (*top);
		(*x) = (*top)->data;
		(*top) = (*top)->next;
		free(p);
		return 1;
	}
	return 0;
}
/*十进制整数转化为任意进制数*/
void Convert(int num, int mode)
{
	int h;
	linkstack top = NULL;
	printf("转化结果为:");
	if (num>0)
	{
		while (num != 0)
		{
			h = num%mode;
			Push(&top, h);
			num = num / mode;
		}
		while (!Empty(top))
		{
			Pop(&top, &h);
			printf("%d", h);
		}
		printf("\n");
	}
	else if (num<0)
	{
		printf("-");
		num = num*(-1);
		while (num != 0)
		{
			h = num%mode;
			if (h >= 10)
			{
				h = h - 10 + 'A';
			}
			Push(&top, h);
			num = num / mode;
		}
		while (!Empty(top))
		{
			Pop(&top, &h);
			printf("%d", h);
		}
		printf("\n");
	}
	else
		printf("%d\n", 0);
}
void main()
{
	int num, mode;
	printf("\n输入要转化的数:");
	scanf("%d", &num);
	printf("输入要转化的进制:");
	scanf("%d", &mode);
	Convert(num, mode);
}

       该整数进制转换算法存在问题如下:首先是只能进行整数的进制转换,并没有将小数进行转换的功能,其次,在进行进制数大于10转换的过程中,会出现输出问题,例如在下面的测试用例中,999的16进制正确转换应为3e7,但程序输出的是3 14 7,无法将大于10的数转换为字符。该问题会在有理数转换为n进制中实现。

 

       对待转换的有理数数先进行小数和整数部分的分离操作,分离操作的重点在于int和double间进行转换时会有精度损失,再对分离后的小数以及整数部分分别判断正负,通过if...else...算法分别实现正数和负数的转化(将负数转为正数)。

       小数部分和整数部分的在进行进制转换时所采用的算法是不同的,整数部分进行的是:与进制相除后的取余和取整操作,且为倒序输出;小数部分进行的是:与进制相乘后的取余和取整操作,且正序输出即可。

#include<stdio.h>
#include<conio.h>
#include<stdlib.h>

typedef char datatype;
typedef struct node
{
	datatype data;
	struct node*next;
}*linkstack;

/*入栈*/
int Push(linkstack *top, datatype x)
{
	linkstack s = (linkstack)malloc(sizeof(struct node));
	if (s == NULL)
		return 0;
	s->data = x;
	s->next = (*top);
	(*top) = s;
	return 1;
}

/*判空*/
int Empty(linkstack top)
{
	if (top == NULL)
		return 1;
	return 0;
}

/*出栈*/
int Pop(linkstack*top, datatype*x)
{
	if (top != NULL)
	{
		linkstack p = (*top);
		(*x) = (*top)->data;
		(*top) = (*top)->next;
		free(p);
		return 1;
	}
	return 0;
}

/*十进制整数转化为任意进制数*/
void Convert_integer(int num, int mode)
{
	int n;
	char h;
	linkstack top = NULL;
	if (num>0)
	{
		while (num != 0)
		{
			n = num%mode;
			h = num%mode +'0';//将int型数字转为对应字符
			if (n >= 10)
			{
				n = n - 10 ;
				h = n + 'A';//将大于10的int型数字转为对应字符
			}
			Push(&top, h);
			num = num / mode;
		}
		while (!Empty(top))
		{
			Pop(&top, &h);
			printf("%c", h);
		}
	}
	else if (num<0)
	{
		printf("-");
		num = num*(-1);
		while (num != 0)
		{
			n = num%mode;
			h = num%mode + '0';//将int型数字转为对应字符
			if (n >= 10)
			{
				n = n - 10;
				h = n + 'A';//将大于10的int型数字转为对应字符
			}
			Push(&top, h);
			num = num / mode;
		}
		while (!Empty(top))
		{
			Pop(&top, &h);
			printf("%c", h);
		}
	}
	else
		printf("0");
}

/*小数转化为任意进制数*/
void Convert_decimal(double num, int mode)
{   
	if (num < 0)
	{
		num = num*(-1);//转为正数
	}
	int a;
	char b;
	double flag;
	
	while (1)//进行死循环
	{
		flag = num * mode;
		a = flag;
		if (a >= 10)
		{
			b = a - 10 + 'A';
		}else{
			b = a + '0';//将int型数字转为对应字符
		}
		printf("%c", b);
		num = flag - a;
		if (num==0)
		{
			break;//break语句用于跳出while死循环
		}
	}
}

void main()
{
	double num, decimal;
	int mode, integer;
	printf("输入要转化的数:");
	scanf("%lf", &num);
	//利用精度损失来实现整数,小数进行分离
	integer = num;
	decimal = num - integer;
	printf("输入要转化的进制:");
	scanf("%d", &mode);
	printf("转化结果:\n");
	Convert_integer(integer, mode);
	printf(".");
	Convert_decimal(decimal, mode);
	//通过整数部分和小数部分的分别转换,拼接而成最终的转换结果
}

则进制数大于10的字符转换问题得到解决,同时也完成了有理数的整数小数的转换。但还是存在问题,对于像-0.89这样的负小数,进行进制转换后,负号会丢失。希望有大佬帮忙解决一下,求求了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值