栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

将十进制有理数转化为m进制数(C语言实现)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

将十进制有理数转化为m进制数(C语言实现)

内容:

若将十进制有理数转换为r进制的数,应如何实现。

步骤:

1.算法分析:

       进行算法分析前,首先需要了解一些进制转换的知识,十进制整数转换二制是采用“除2取余,逆序输出”的方法,即辗转相除法。但是有理数不止包含整数,也包含小数,小数的转换与整数略有不同。

       那么怎么利用辗转相除法进行整数进制转化呢?这里以789.8125为例进行二进制转换:

       因为整数和小数的转化方法略有不同,所以将789.8125分开处理,先处理整数部分:

       789 / 2 = 394  (余 1)

       394 / 2 = 197  (余 0)

       197 /2 = 98    (余 1)

       98 / 2 = 49    (余 0)

       49 / 2 = 24    (余 1)

       24 / 2 = 12    (余 0)

       12 / 2 = 6     (余 0)

       6 / 2 = 3      (余 0)

       3 / 2 =1       (余 1)

      1 / 2 =0       (余 1)

         则789的十进制转二进制结果为:1100010101

        由此可见,10进制转2进制就是,除2取余;再用商除2取余,一直到被除数(商)为0,余数的逆序就是该2进制数。所以,10进制转m进制就是,除m取余;再用商除m取余,一直到被除数(商)为0,余数的逆序就是该m进制数。

         上述即为整数转化进制的辗转相除法,但是小数部分要怎么处理呢?

        以十进制转二进制为例,十进制小数部分转二进制小数是采用“乘2取整,顺序排列”法。具体做法是:用2乘十进制小数,可以得到积,将积的整数部分取出,再用2乘余下的小数,又得到一个积,再将积的整数部分取出,如此进行,直到积中的小数部分为0,或者达到所要求的精度为止。然后把取出的整数部分按顺序排列起来,先取的整数作为二进制小数的高位有效位,后取的整数作为低位有效位。

        下面处理789.8125小数部分,将0.8125转换为二进制小数:

         0.8125 * 2 = 1.6250 ……….取整数:1

         0.6250 * 2 = 1.2500 ……….取整数:1

         0.2500 * 2 = 0.5000 ……….取整数:0

         0.5000 * 2 = 1.0000 ……….取整数:1

       所以0.8125转化为二进制结果为0.1101。

       所以789.8125转化为二进制结果为:1100010101.1101

       另外,有些数字在转换过程中会发生循环现象,会存在损失精度现象,这里不展开讨论。

       由上述过程可以看到,转换过程不同于整数的辗转相除法。所以在进行有理数转换时,需要将整数部分和小数部分分开进行转换。整数部分依然使用辗转相除法进行计算。小数使用(假设转为m进制)“乘m取整,顺序排列”的方法。

       同时考虑到较大进制中存在着字母,所以对于转换的目标进制也要考虑。

       因此算法设计是用三个函数分别实现链栈的入栈、判断栈空和出栈操作。先对传进来的数进行取小数操作,并判断是否有小数,无小数利用if……else语句分别实现整数和负数的转化,转化的思想是辗转相除法。小数部分乘以对应进制,进行进制的转换。若转化的进制大于10,则用字母A、B、C、D等表示,再将两部分合起来。整数部分利用栈的特性,先进后出,得到对应进制。小数部分因为是顺序输出,是先进先出,所以不需要栈,直接输出即可。

2.概要设计:

函数作用
Seqstack()初始化一个顺序栈
Conversion()实现整数部分转换
Pop()实现元素的出栈操作
Empty()实现栈的判空操作
Conver()实现小数部分的转换操作

3.程序的流程图

  

 4.源代码如下(编译环境:vc++6.0):

#include 
#include 
#include
#define maxsize 1000000

typedef struct//栈
{
	char c[maxsize];
	int top;
}seqstack;

int empty_seqstack(seqstack *s)//判断栈是否满
{
	if(s->top==-1)
		return 1;
	else
		return 0;
}

void push_seqstack(seqstack *s,char x)//入栈
{
	if(s->top==maxsize-1)           //判断栈是否满
		printf("stack is fulln");
	else
	{
		s->top++;   //先是top加1,避免覆盖原始数据
		s->c[s->top]=x;
	}
}

void pop_seqstack(seqstack*s)
{
	char x;
	while(s->top!=-1) //判断是否为空栈
	{
		x=s->c[s->top];
		printf("%c",x);
		s->top--;
	}

}

void conversion(int a,int r,seqstack *s)
{
	char x;
	while(a!=0)
	{
		if(a%r<=9)
		{
			x=a%r+'0';
			push_seqstack(s,x);
		}
		else
		{
			x=a%r+'A'-10;
			push_seqstack(s,x);
		}
		a=a/r;
	}
}
void conver_decimal(float de,int r)
{
	float flag;
	de =de -(int)de;//先是对传进来的实数进行了取小数
	int dc;
	char x1;
	char s[100000]=".";
	int i=1;
	flag =de; //用于判断实数是否有小数部分

	while(de>0.000001)
	{
		if((int)(de*r)<=9)
		{
			dc = (int)(de*r);   //小数部分乘以对应进制,进行进制的转换
			de =de *r;
			de = de - dc;
			x1 = dc +'0';
			s[i++]=x1;
		}
		else
			{
			dc = (int)(de*r);
			de =de *r;
			de = de - dc;
			x1 = dc +'A'-10;//进制大于10,,则用字母A,B,C来表示
			s[i++]=x1;
		}
	}
	if(flag!=0)
	{
		printf("%s",s);
	}
}

int main()
{
	float a;
	int r;
	seqstack *s;
	s=(seqstack*)malloc(sizeof(seqstack));
	s->top=-1; // -1定义为栈空
	printf("请输入要转换的数和进制n");
	scanf("%f %d",&a,&r);
	conversion(a,r,s); //将数字对的整数部分转换成对应进制
	pop_seqstack(s); //利用栈的特性,先进后出,得到对应进制。
	conver_decimal(a,r); //小数部分算法,不需要栈,先进先出即可,因此顺序输出
	return 0;
}

 5.样例测试:

5.1 纯小数二进制测试

5.2 整数+小数二进制测试:

5.3  整数+小数其他进制(16进制)测试:

5.4 小数其他进制(16进制)测试:

     至此,问题已全部解决。但还存在着一个小问题,就是纯小数输出时,小数点前面少0,不过无伤大雅。感谢阅读。 创作不易,走路路过,一键三联一下呗。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/330090.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号