poj 1930 Dead Fraction

Description

Mike is frantically scrambling to finish his thesis at the last minute. He needs to assemble all his research notes into vaguely coherent form in the next 3 days. Unfortunately, he notices that he had been extremely sloppy in his calculations. Whenever he needed to perform arithmetic, he just plugged it into a calculator and scribbled down as much of the answer as he felt was relevant. Whenever a repeating fraction was displayed, Mike simply reccorded the first few digits followed by "...". For instance, instead of "1/3" he might have written down "0.3333...". Unfortunately, his results require exact fractions! He doesn't have time to redo every calculation, so he needs you to write a program (and FAST!) to automatically deduce the original fractions. 
To make this tenable, he assumes that the original fraction is always the simplest one that produces the given sequence of digits; by simplest, he means the the one with smallest denominator. Also, he assumes that he did not neglect to write down important digits; no digit from the repeating portion of the decimal expansion was left unrecorded (even if this repeating portion was all zeroes).

Input

There are several test cases. For each test case there is one line of input of the form "0.dddd..." where dddd is a string of 1 to 9 digits, not all zero. A line containing 0 follows the last case.

Output

For each case, output the original fraction.

Sample Input

0.2...
0.20...
0.474612399...
0

Sample Output

2/9
1/5
1186531/2500000

Hint

Note that an exact decimal fraction has two repeating expansions (e.g. 1/5 = 0.2000... = 0.19999...).

Source

题目给出一个无限循环小数,求分母最小的分数形式,因为循环节具体是多少位是未知的(至少一位),所以枚举,选择分母最小的哪个。
小数化成分数很容易,循环部分化成分数用解方程法(见注释)。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#define MAX 305
#define inf 0x3f3f3f3f
using namespace std;
/*
小数转换成分数,分子分母都是整数,所以转化为整数来求
小数部分分为不循环部分和循环部分,由于不清楚哪部分是循环的,然而题目要求分母最小的,所以枚举不循环的部分剩下的是循环部分
然后计算结果
*/
int gcd(int a,int b) {///最大公因数
    return b ? gcd(b,a % b) : a;
}
char s[30];
int main() {
    while(scanf("%s",s) && s[1]) {
        int mina = 1000000000,minb = 1000000000;///初始化分子分母 更新最小
        int dec = 0,c = 0;///dec以整数形式 记录给出的小数部分 c记录位数
        for(int i = 2;s[i] != '.';i ++,c ++) {///遍历字串
            dec = dec * 10 + s[i] - '0';
        }
        for(int num = dec / 10,j = 10,i = 1;i <= c;i ++,j *= 10,num /= 10) {///num为非循环部分,每次减少一位 i是衡量循环部分的位数 j是循环部分的10的幂
            ///下面的计算是根据 假如循环部分是末尾i位 那么 j = 10 ^ i
            ///非循环部分 是 (dec/j) / 10^(c - i)
            ///那么循环部分呢,可以用解方程法,举个例子 x = 0.33333...  10x - x = 3.3333... - 0.33333 = 3 ,9x = 3,x =1 / 3
            ///再比如0.1212... 10^2x - x = 12,x = 12 / 99  也就是说跟循环节以及其位数有关 假如循环节是N,位数是x,那么化成的分数就是N/(10^x - 1)
            ///如果是0.001212...  就是在分母多除以一个10^2罢了,这样这道题的循环部分就有了
            ///即 循环部分是后i位,前c - i位是非循环部分 那么循环部分表示为  dec % j / ((j - 1) * 10^(c - i))
            ///两部分相加通分就是答案   带入 dec % j = dec - dec / j * j   得 (dec - dec / j) / ((j - 1) * 10^(c - i))
            int a = dec - num;///dec - dec / j
            int b = (int)pow(10,c - i) * (j - 1);
            int k = gcd(a,b);
            if(b / k < minb) {
                mina = a / k;
                minb = b / k;
            }
        }
        printf("%d/%d
",mina,minb);
    }
}
原文地址:https://www.cnblogs.com/8023spz/p/9471077.html