1. 程式人生 > >HDOJ 1717 小數化分數2 (數學,迴圈小數化分數詳細講解)

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;
}