HDOJ 1717 小数化分数2 (数学,循环小数化分数详细讲解)



小数化分数2

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4043    Accepted Submission(s): 1649


Problem Description
Ray 在数学课上听老师说,任何小数都能表示成分数的形式,他开始了化了起来,很快他就完成了,但他又想到一个问题,如何把一个循环小数化成分数呢?
请你写一个程序不但可以将普通小数化成最简分数,也可以把循环小数化成最简分数。
 

Input
第一行是一个整数N,表示有多少组数据。
每组数据只有一个纯小数,也就是整数部分为0。小数的位数不超过9位,循环部分用()括起来。
 

Output
对每一个对应的小数化成最简分数后输出,占一行。
 

Sample Input
  
  
3 0.(4) 0.5 0.32(692307)
 

Sample Output
  
  
4/9 1/2 17/52
 

题解:不循环小数化分数很简单,现在这里介绍循环小数化分数的方法,

 日本野口哲典在《天哪!数学原来可以这样学》中介绍了如何将循环小数转化成分数的方法,现介绍如下:
 
1.循环小数0.7272……循环节为7,2两位,因此化为分数为72/99=1/8.即有几位循环数字就除以几个9。又如

0.123123……循环节为1,2,3三位,因此化为分数为123/999=41/333.这种方法只适用于从小数点后第一位就开始

循环的小数,如果不是从第一位就开始循环的小数,必须用下面的方法。
 
 2.循环小数0.41666……先把0.41666……乘以100得41.666……,可以理解为41+0.666……,所以写成分数为

41+6/9=41+2/3=125/3.因为开始乘以了100,所以再除以100,即125/3÷100=125/300=5/12.


关于这里介绍的转化方法的原理是解一元一次方程。

如下:

1.把0.232323... 化成分数 . 
设X=0.232323... 
因为0.232323... == 0.23 + 0.002323... 
所以 X = 0.23 + 0.01X 
解得:X = 23/99 

2.把0.1234123412341234...化成分数 . 
设X=0.1234123412341234... 
因为0.1234123412341234... == 0.1234 + 0.000012341234... 
所以X = 0.1234 + 0.0001X 
解得:X = 1234/9999 

3.把0.56787878...化成分数, 
因为0.56787878...= 0.56 + 0.01 * 0.787878... 
所以设X=0.787878...则X=0.78 + 0.01X 
所以X = 78/99 
所以原小数0.56787878...=0.56+ 0.01X = 0.56 + 0.078/99 = 2811/4950 



代码如下:

#include<cstdio>
#include<cmath>
#include<cstring>
char str[20];

int gcd(int n,int m)
{
	int i;
	while(m)
	{
		i=n%m;
		n=m;
		m=i;
	}
	return n;
}

int main()
{
	int t,len,j,k,cnt,num,len_r,inter,i;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%s",str);
		len=strlen(str);
		if(!strchr(str,'(' ))//没有循环节的情况 
		{
			cnt=0; num=1;
			for(i=len-1;i>1;i--)
				cnt+=(str[i]-'0')*pow(10.0,(len-i-1)*1.0);//分子 
			for(i=2;i<len;++i)
				num*=10;//分母 
			int res=gcd(num,cnt);
			num/=res;
			cnt/=res;
			printf("%d/%d\n",cnt,num);
		}
		else//有循环节的情况 
		{
			for(i=2;i<len;++i)
			{
				if(str[i]=='(')
				{
					j=i-2;//小数点后不循环处的长度 
					k=i;
				}
				if(str[i]==')')
				{
					len_r=i-k-1;//循环处的长度 
				}
			}
			cnt=0;num=0;
			for(i=k+1;i<=len-2;i++) 
			{
				cnt=cnt*10+(str[i]-'0');//分子 
				num=num*10+9;//分母 
			}
			inter=0;
			for(i=k-1;i>1;--i)
				inter+=(str[i]-'0')*pow(10.0,(k-1-i));//求不循环的部分 
			int res=gcd(num,cnt);
			num/=res;
			cnt/=res;
			cnt+=(inter*num);
			for(i=0;i<j;++i)//因为数字扩大了10^j倍,分母也要扩大相同的倍数 
				num*=10;
			res=gcd(num,cnt);
			num/=res;
			cnt/=res; 
			printf("%d/%d\n",cnt,num);
		}
	}
	return 0;
}





  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值