【编程之美】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;
}

 

posted @ 2014-10-31 12:59  匡子语  阅读(526)  评论(0编辑  收藏  举报