小数化分数 模拟题

小数化分数

Problem Description
将给出的小数化为分数
Input
只有一行,为要转换的小数(正负均有)。
注意:小数的格式有好几种。为了方便起见,循环部分均被括号括起来了。
有前导0或后导0的例子:09.400(输出47/5)
纯循环小数的例子:0.(3)(输出1/3)
混循环小数的例子:0.5(142857)(输出18/35)
输入数据都是正确的,不用判错。保证如果有循环节,那么输入的最后一个字符必然是右括号;如果有前导0,一定是正数。
Output
只有一行,为非带分数(也就是说只有真分数或假分数)的形式。
注意分数线一定为左斜杠。
Sample Input 1:
09.400
Sample Output 1:
47/5
Sample Input 2:
0.(3)
Sample Output 2:
1/3
Sample Input 3:
0.5(142857)
Sample Output 3:
18/35
Tip
题目大意:给定一个(可能有整数部分、有可能有前导0和后导0、有可能是纯循环或混循环或不循环)的小数,求出其非带分数(也就是说只有真分数或假分数)表示形式。
要注意的是,1.(9)、1.9(9)和4/2都表示2这个数字。
Data Instraint
100%保证运算过程中及输出结果的值不会超过2^(64-1)。

观察本题,容易发现,此题目要求我们将所给小数化成分数。
对于题目所给小数的读入各显神通,在这里不再多说。
一开始,我们的思路是,假定分数a/b,使其逼近题目所给的值,并且根据其与题目所给小数的大小比较,逐次增加a或b的值,来使其逼近题目所给小数。
不过,这种方法其本身正确性便值得推敲,二来时间消耗大,故不为所取。
所以,我们继续观察本题。经过猜想、推测、验证,很容易知道,对于一个循环的数0.(x),它化成分数的形式应该是 x/99……99 (9的个数就是x的位数)
那么,我们通过这个东西,就可以快速的将小数部分的分母分子求出,进行通分约分,得到最后答案。
当然,要注意的是,由于数据较大,通分过程要讲究顺序,以免运算出现过大的数。
代码如下。

#include <cstdio>
 
typedef long long LL;
 
using namespace std;
 
LL a=0,b=1,la=0,lb=0,x=0;
LL num;
 
LL gcd(LL a,LL b)
{
    return b?gcd(b,a%b):a;
}
 
void read()
{
    char c=getchar();
    int f=0;
    bool bo=false;
    while (((c<'0')||(c>'9'))&&(c!='-'))
        c=getchar();
    if (c=='-')
        f=1,c=getchar();
    while ((c>='0')&&(c<='9'))
        x=(x<<3)+(x<<1)+c-'0',c=getchar();
    if (c=='.')
    {
        c=getchar();
        loop :
            switch (c)
            {
                case '(':
                    bo=true;
                    c=getchar();
                    goto loop;
                default :
                    if ((c>='0')&&(c<='9'))
                        if (bo)
                        {
                            la=(la<<3)+(la<<1)+c-'0';
                            c=getchar();
                            (lb*=10)+=9;
                            goto loop;
                        }
                        else
                        {
                            if (c!='0')
                            {
                                for (;num;num--)
                                    a*=10,b*=10;
                                a=(a<<3)+(a<<1)+c-'0',b*=10;
                            }
                            else
                                num++;
                            c=getchar();
                            goto loop;
                        }
            }
    }
    LL g;
    if (bo)
    {
        g=gcd(gcd(a,b),la);
        a/=g;b/=g;la/=g;
        g=gcd(la,lb);
        la/=g;lb/=g;
        (a*=lb)+=la;
        b*=lb;
    }
    g=gcd(a,b);
    a/=g;b/=g;
    a+=b*x;
    g=gcd(a,b);
    a/=g;b/=g;
    if (f)
        printf("-");
    if (b!=1)
        printf("%lld/%lld",a,b);
    else
        printf("%lld",a);
    return ;
}
 
 
int main()
{
    read(); 
    return 0;
}

猜你喜欢

转载自blog.csdn.net/CutieDeng/article/details/82860287