1. 程式人生 > >小數化分數 模擬題

小數化分數 模擬題

小數化分數

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;
}