【编程之美】2.6 精确表达浮点数

题目: 给一个有限小数 或者 无限循环小数, 用分母最小的方式用分数精确的表达这个数字。 括号中表示循环部分,如:

0.3  , 0.3(3), 0.3(0)

 

思路:我一看,傻眼了,想了两下不想想了,就在网上找循环小数转分数,结果居然是小学奥赛题!我郁闷的很啊.....

拿 1.2(34)来举例子吧

1.2(34) * 10 = 12.34343434...

1.2(34) * 1000 = 1234.3434...

1.2(34) * 1000  - 1.2(34) * 10 = 1234 - 12

990 * 1.2(34) = 1222

1.2(34) = 1222 / 990

 

然后再约分,分子分母同时除以他们的最大公约数就好了。

代码输入是用字符串输入的,需要判断是否有循环节和循环节是否为0

#include <stdio.h>

#include <string.h>



typedef struct  Fraction

{

    int numerator;

    int denominator;

}Fraction;



//返回num * 10^pow

int Tens(int num, int pow)

{

    for(int i = pow; i != 0; i--)

    {

        num *= 10;

    }

    return num;

}



//辗转相除求最大公约数

int mod(int num1, int num2)

{

    int a, b;

    a = (num1 > num2) ? num1 : num2;

    b = (num1 < num2) ? num1 : num2;



    int r = a % b;

    if(r == 0)

        return b;

    else

    {

        a = b;

        b = r;

        return mod(a, b);

    }

}



Fraction getFractionExperssion(char * in)

{

    int intefer = 0; //整数部分

    int WithoutLoop = 0; //不循环部分

    int WithLoop = 0; //循环部分

    int powWithoutLoop = 0; //不循环部分到第几位小数

    int powOfLoop = 0; //循环部分到第几位小数

    

    int numerator = 0; //分子

    int denominator = 0; //分母

    Fraction ans;

    

    int tmp = 0;

    int tmpPowWithoutLoop = 0;

    int tmpPowOfLoop = 0;

    char * tmpin = in;

    bool bHasLoop = false;

    while(*tmpin != '\0')

    {

        if(*tmpin >= '0' && *tmpin <= '9')

        {

            tmp = tmp * 10 + ((*tmpin) - '0');

            tmpPowWithoutLoop++;

            tmpPowOfLoop++;

        }

        else if(*tmpin == '.')

        {

            tmpPowWithoutLoop = 0;

        }

        else if(*tmpin == '(')

        {

            powWithoutLoop = tmpPowWithoutLoop;

            WithoutLoop = tmp;

            tmpPowOfLoop = 0;

            tmp = 0;

            bHasLoop = true;

        }

        else if(*tmpin == ')')

        {

            powOfLoop = tmpPowOfLoop;

            WithLoop = tmp;

            tmp = 0;

        }

        else

        {

            printf("input error!!");

        }

        tmpin++;

    }



    //处理没有()的情况

    if(!bHasLoop)

    {

        WithoutLoop = tmp;

        powWithoutLoop = tmpPowWithoutLoop;



    }



    if(WithLoop == 0) //本身不是循环小数

    {

        //得到分子分母

        numerator = WithoutLoop;

        denominator = Tens(1, powWithoutLoop);



        //求最大公约数

        int gcd = mod(numerator, denominator);



        //使答案的分子分母最小

        ans.denominator = denominator / gcd;

        ans.numerator = numerator / gcd;



        printf("%s = %d / %d\n", in, ans.numerator, ans.denominator);

        return ans;

    }

    else //是循环小数

    {

        numerator = Tens(WithoutLoop, powOfLoop) + WithLoop - WithoutLoop;

        denominator = Tens(1, powOfLoop + powWithoutLoop) - Tens(1, powWithoutLoop);



        int gcd = mod(numerator, denominator);

        

        ans.denominator = denominator / gcd;

        ans.numerator = numerator / gcd;



        printf("%s = %d / %d\n", in, ans.numerator, ans.denominator);

        return ans;



    }

}



int main()

{

    char * in1 = "3.3(3)";

    char * in2 = "2.3(12)";

    char * in3 = "0.300(0)";

    getFractionExperssion(in1);

    getFractionExperssion(in2);

    getFractionExperssion(in3);



    return 0;

}

 

你可能感兴趣的:(编程之美)