天天看點

小數化分數(C++ 代碼講解很詳細)

【問題描述】

任何小數都能表示成分數的形式,對于給定的小數,編寫程式其化為最簡分數輸出,小數包括簡單小數和循環小數。

【輸入形式】

第一行是一個整數N,表示有多少組資料。

每組資料隻有一個純小數,也就是整數部分為0。小數的位數不超過9位,循環部分用()括起來。

【輸出形式】

對每一個對應的小數化成最簡分數後輸出,占一行

【樣例輸入】

3

0.(4)

0.5

0.32(692307)

【樣例輸出】

4/9

1/2

17/52

解題思路:

對于本題的整數部分都是零的

1.對于普通不包含循環體的小數(其中有無限不循環小數), 其化為分數都是讓小數點後組成的數除以10的此數的位數次方,比如0.1234=1234/10000。

2.對于無限循環小數來說,化為分數的方法就是看循環體有幾位,則分母中就包含幾個9,如果小數部分除循環體外還有數,則有幾個數,就在分母後面加幾個零。例如0.32(692307),分母就為99999900,循環體有6位是以分母有6個9,小數部分除循環體外還有兩位數,則分母再加兩個零即可。分子則是由小數部分包含循環體組成的數減去非循環體組成的數,例如:0.32(692307),分子為32692307-32

AC代碼如下:

#include<stdio.h>
#include<math.h> 
#include<string.h>
#include<algorithm>
using namespace std;
int main(){
	int i,j,len,t1,t2,t3,t4,t5,T,flag,sum1,sum2;
	char str[200];
	scanf("%d",&T);
	while(T--){
		flag=t1=t2=t4=t5=sum1=sum2=0;
		scanf("%s",str);
		len=strlen(str);
		for(i=2;i<len;i++){//去掉整數部分的零和小數點,直接從小數部分也就是2開始循環
			if(str[i]=='('||str[i]==')'){
				flag=1;//判斷是否包含循環體
			}
			if(flag==1&&str[i]>='0'&&str[i]<='9')
				sum2++;//計算循環體的位數,友善計算分母有多少個9 
			if(flag==0){
				t4=t4*10+str[i]-'0';//非循環體組成的整數
				sum1++;//非循環體位數,友善計算在分母上添幾個零
			} 
			if(str[i]>='0'&&str[i]<='9')
				t5=t5*10+str[i]-'0';//小數點後所有數組成的整數 
		}
		if(flag==0){
			for(i=2;i<len;i++){
				t1=t1*10+(str[i]-'0');//沒有循環體時,計算出分子
			}
			t2=pow(10,len-2);
			t3=__gcd(t1,t2); //求出兩數的最大公約數
			printf("%d/%d\n",t1/t3,t2/t3);
		}
		else{
			t1=t5-t4;//有循環體時分子的值
			for(i=1;i<=sum2;i++)
				t2=t2*10+9;//計算9的個數
			t2=t2*pow(10,sum1); 
			t3=__gcd(t1,t2);
			printf("%d/%d\n",t1/t3,t2/t3);
		}
	}
	return 0;
}