HDU 1717 小数化分数2 数学题

解题报告:输入一个小于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 }            
View Code
原文地址:https://www.cnblogs.com/xiaxiaosheng/p/3257790.html