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

2020-10-04 07:00:11

【問題描述】
任何小數都能表示成分數的形式,對於給定的小數,編寫程式其化為最簡分數輸出,小數包括簡單小數和迴圈小數。
【輸入形式】
第一行是一個整數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;
}