解题报告:输入一个小于1的小数,让你把这个数转化成分数,但注意,输入的数据还有无限循环的小数,循环节用一对括号包含起来。
之前还没有写过小数转分数的题,当然如果没有循环小数的话,应该比较简单,但是这题要求有循环小数。其实这里要用到一个很巧妙的方法,这里以0.4444444....这个无限循环小数来作为例子,0.444...*10 - 0.444.... = 4,又有左边的0.444...可以提出来,所以得到:
0.444....(10-1) = 4;
即0.444....*9 = 4,
所以无限循环小数就可以表示为4/9,如果循环节前还有数字的话,只要把前面的那部分分离出来,分别转化,然后把两个分数加起来就可以了。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 using namespace std; 6 typedef __int64 INT; //最好用__int64,一开始没用,一出现大数就溢出了 7 INT f[13] = {1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000}; 8 INT GCD(INT a,INT b) { 9 return a%b==0? b:GCD(b,a%b); 10 } 11 12 int main() { 13 int t; 14 INT a,b,c,d; 15 char S[40],T[40]; 16 scanf("%d",&t); 17 while(t--) { 18 scanf("%s",S); 19 a = c = 0; //分子一律初始化为0 20 b = d = 1; //分母一律初始化为1 21 INT loc1 = 0,loc2 = 0,len = strlen(S),k = 0,flag = 0; 22 for(int i = 0;i<len;++i) { 23 if(flag) 24 T[k++] = S[i]; 25 if(S[i] == '(') { //标记括号的位置以及否有循环 26 loc1 = i; 27 flag = 1; 28 } 29 } 30 T[k-1] = NULL; 31 int lent = strlen(T); 32 if(flag) { //求循环部分的分数 33 c = atoi(T); 34 d = f[lent] - 1; 35 } 36 if(loc1 > 1 || !flag) { 37 if(flag) 38 S[loc1] = NULL; 39 int lens = strlen(S+2); 40 d *= f[lens]; //这个部分别忘了,当小数点后面有不循环的部分时,循环部分要缩小相应的倍数 41 a = atoi(S+2); 42 b = f[lens]; 43 } 44 INT A = a*d + b*c; 45 INT B = b*d; 46 INT C = A; 47 A = A /= GCD(A,B); 48 B /= GCD(C,B); 49 printf("%I64d/%I64d ",A,B); 50 } 51 return 0; 52 }