1. 程式人生 > >hdu 1717 小數化分數2 (數學)

hdu 1717 小數化分數2 (數學)

小數化分數2

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2022    Accepted Submission(s): 813


Problem Description Ray 在數學課上聽老師說,任何小數都能表示成分數的形式,他開始了化了起來,很快他就完成了,但他又想到一個問題,如何把一個迴圈小數化成分數呢?
請你寫一個程式不但可以將普通小數化成最簡分數,也可以把迴圈小數化成最簡分數。
Input 第一行是一個整數N,表示有多少組資料。
每組資料只有一個純小數,也就是整數部分為0。小數的位數不超過9位,迴圈部分用()括起來。
Output 對每一個對應的小數化成最簡分數後輸出,佔一行。 Sample Input 3 0.(4) 0.5 0.32(692307) Sample Output 4/9 1/2 17/52 Source

眾所周知,有限小數是十進分數的另一種表現形式,因此,任何一個有限小數都可以直接寫成十分之幾、百分之幾、千分之幾……的數。那麼無限小數能否化成分數? 

首先我們要明確,無限小數可按照小數部分是否迴圈分成兩類:無限迴圈小數和無限不迴圈小數。無限不迴圈小數不能化分數,這在中學將會得到詳盡的解釋;無限迴圈小數是可以化成分數的。那麼,無限迴圈小數又是如何化分數的呢?由於它的小數部分位數是無限的,顯然不可能寫成十分之幾、百分之幾、千分之幾……的數。其實,迴圈小數化分數難就難在無限的小數位數。所以我就從這裡入手,想辦法“剪掉”無限迴圈小數的“大尾巴”。策略就是用擴倍的方法,把無限迴圈小數擴大十倍、一百倍或一千倍……使擴大後的無限迴圈小數與原無限迴圈小數的“大尾巴”完全相同,然後這兩個數相減,“大尾巴”不就剪掉了嗎!我們來看兩個例子:

⑴    把0.4747……和0.33……化成分數。

想1:        0.4747……×100=47.4747……   

0.4747……×100-0.4747……=47.4747……-0.4747……

(100-1)×0.4747……=47

即99×0.4747…… =47 

那麼  0.4747……=47/99



想2: 0.33……×10=3.33……

0.33……×10-0.33……=3.33…-0.33……

(10-1) ×0.33……=3

即9×0.33……=3

那麼0.33……=3/9=1/3

由此可見, 純迴圈小數化分數,它的小數部分可以寫成這樣的分數:純迴圈小數的迴圈節最少位數是幾,分母就是由幾個9組成的數;分子是純迴圈小數中一個迴圈節組成的數。

⑵把0.4777……和0.325656……化成分數。

想1:0.4777……×10=4.777……①

0.4777……×100=47.77……②

用②-①即得: 

0.4777……×90=47-4

所以, 0.4777……=43/90



想2:0.325656……×100=32.5656……①

0.325656……×10000=3256.56……②

用②-①即得: 

0.325656……×9900=3256.5656……-32.5656……

0.325656……×9900=3256-32

所以, 0.325656……=3224/9900

將純迴圈小數改寫成分數,分子是一個迴圈節的數字組成的數;分母各位數字都是9,9的個數與迴圈節中的數字的個數相同.

  將混迴圈小數改寫成分數,分子是不迴圈部分與第一個迴圈節連成的數字組成的數,減去不迴圈部分數字組成的數之差;分母的頭幾位數字是9,末幾位數字是0,9的個數跟迴圈節的數位相同,0的個數跟不迴圈部分的數位相同.

#include <cstdio>
#include <algorithm>
#include <cstring>
//#define int long long
using namespace std;

int gcd(int a, int b){
    while (b){
        int tmp = a;
        a = b;
        b = tmp % b;
    }
    return a;
}

int n,j;
int part1, part2, pow, sum_val, tmp_pow;
char s[100];

int get_val(int &pos){
    int ans = 0;
    while (s[pos] && s[pos] != '(' && s[pos] != ')'){
        sum_val = sum_val *10 + s[pos] - '0';
        ans = ans * 10 + s[pos++] - '0';
        pow = pow * 10;
    }
    return ans;
}

void init(){
    j = 2;
    sum_val = 0;
    pow = 1;
    part1 = part2 = sum_val = 0;

    part1 = get_val(j);
    tmp_pow = pow;
    if (s[j] == '(') ++j;
    part2 = get_val(j);
}
char c = '/';
int main(){
    scanf("%d", &n);
    //getchar();
    for (int i = 1; i <= n; ++i){
        //gets(s);
        scanf("%s", s);
        init();

        if (!part2){
            int GCD = gcd(tmp_pow, sum_val);
            printf("%d%c%d\n", sum_val / GCD, c, tmp_pow / GCD);
        }
        else{
            int fenmu = pow - tmp_pow;
            int fenzi;
            if (part1) fenzi = sum_val - part1;
            else fenzi = part2;
            int GCD = gcd(fenzi, fenmu);
            printf("%d%c%d\n", fenzi / GCD, c, fenmu / GCD);
        }

    }
    return 0;
}