HDU1717循环小数化成分数

A - 
Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u

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
#include<stdio.h>
#include<string.h>
#include<math.h>
int main()
{
    long long _;// 循环条件我都用了long long真是被wa怕了。 
    scanf("%I64d",&_);
    char num[12],crl[12],c;
    long long o,flag,m,temp,yue,i;
    while(_--)
    {

        long long cntt=0;
        int flagg=1;
        o=0;
        memset(num,0,sizeof(num));
        memset(crl,0,sizeof(crl));
        flag=1;getchar();
        while(1)
        {

                if((c=getchar())=='.') break;
                else if(c==10){printf("0/1\n");cntt=1;break;}
        }
        if(cntt) continue;
        while(1)
        {
           if( (c=getchar())!='('&&c!='\n') num[o++]=c;
           else if(c=='\n') {flag=0;break;}
           else break;

        }
        o=0;
        if(flag)
        {
            while(1)
            {
                if( (c=getchar())!=')') crl[o++]=c;
                else break;
            }
        }
        m=strlen(num);
       long long mu=1;
        for(;m>0;m--)
        {
            mu*=10;
        }
       long long zi=0;

       if((m=strlen(num))!=0)
       {
            for(i=0;num[i]!=0;i++) zi+=(num[i]-'0')*floor(pow(10.0,(double)(--m))+0.5);
            long long tezi=zi,temu=mu;

            if(zi==0&&strlen(crl)==0) {printf("0/1\n");continue;}
            else if(zi==0){zi=0;mu=1;flagg=0;}
            if(flagg)
            {
                while(1)                                              //辗转相除
                {
                    if((temp=temu%tezi)!=0)
                    {
                        temu=tezi;
                        tezi=temp;

                    }
                    else{yue=tezi;break;}
                }
                mu=mu/yue;
                zi=zi/yue;
                if(!flag) {printf("%I64d/%I64d\n",zi,mu);continue;}
            }

          //  else if(!flag) {printf("0/1\n");continue;}
       }
    //   else if(!flag){printf("0/1\n");continue;}


        m=strlen(crl);
        long long zi2=0;
        for(i=0;crl[i]!=0;i++)  zi2+=(crl[i]-'0')*floor(pow(10.0,(double)(--m))+0.5);
       long long mu2=(floor(pow(10.0,(double)(strlen(crl)))+0.5)-1)*floor(pow(10.0,(double)(strlen(num)))+0.5);
       long long temu2=mu2,tezi2=zi2;
         while(1)
        {
            if((temp=temu2%tezi2)!=0)
            {
                temu2=tezi2;
                tezi2=temp;

            }
            else{yue=tezi2;break;}
        }
       mu2/=yue;zi2/=yue;
       long long szi=mu2*zi+mu*zi2; long long smu=mu*mu2;
      long long tesmu=smu,teszi=szi;
         while(1)
        {
            if((temp=tesmu%teszi)!=0)
            {
                tesmu=teszi;
                teszi=temp;

            }
            else{yue=teszi;break;}
        }
        smu/=yue;szi/=yue;
        if(strlen(crl)||strlen(num))printf("%I64d/%I64d\n",szi,smu);
        else printf("0/1\n");
    }
    return 0;

}//  调了快三个小时才调出来AC。自己用long long纯属多余,害怕爆int,其实不会爆,天猫就没用long long
//自己代码用了一个0的特例,如果输入为0 ,输出为0/1,要不这样我的辗转相除部分会出现除0的情况。而天猫的辗转相除的外部函数很好的解决了这个问题、 
//这是天猫的代码。 

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
int gcd(int b,int a)                           //递归外部函数的构造对于初学者的确有点难度,但是不能逃避。还是要多练练这种递归思维。 
{
    if(b==0)                                 //当输入为0的时候b为0直接返回a。结果是0/1。 用外部函数来实现辗转相除读形参赋值然后运算,不用担心改变分子分母,我还定义了另外6个变量来作为中间值。 
        return a;
    else
    	return gcd(a%b,b);
}

int N,i,len,s1,s2,p1,p2;
int t1,t2,t;
char decimal[25];

int main(){
    scanf("%d",&N);
    while(N--)
	{
        scanf("%s",decimal);                    //直接用%s读入,然后用循环条件检测循环节长度。,而我用getchar一个一个读,还要有\n的问题和存在没循环节的情况,比较蠢。 
        len = strlen(decimal);
        i=0;
        while(decimal[i]!='.'&&i<len) i++;
        i++;s1=0;p1=1;
        while(decimal[i]!='('&&i<len)                     //天猫的这几个while做的事情效率很高,完成了三件事情:1.用i++检测循环节长度。2.把字符的数字转化成十进制数3.构造出分母P1。
		                                                   //当时我就害怕构造分母的时候用循环就用了pow,由于有浮点到整型的转化,和误差消除,都极消耗笔墨。但是自己还是用了循环完成了天猫的2. 
														 
		{
            s1=s1*10+decimal[i]-'0';
            i++;
            p1*=10;                                         
        }
        i++;s2=0;p2=1;
        while(decimal[i]!=')'&&i<len)
		{
            s2=s2*10+decimal[i]-'0';
            i++;
            p2*=10;
        }
        if(s2)
		{
            t1 = s1*(p2-1)+s2;
            t2 = p1*(p2-1);
        }
        else
		{
            t1=s1;
            t2=p1;
        }
        t = gcd(t1,t2);
        printf("%d/%d\n",t1/t,t2/t);
    }
    return 0;

}
/*代码长度比我缩短了三分之一,但是思路一模一样。可见编程实力差距、、*/ 




/*我和天猫的思路都是这样:比如 0.(4)设转化成的分数为X ,有 10*X-4=X。 0.(M)转化成分数即10*X-M=X
比如0.abc(defg) ,先把0.000(defg)转化成分数,再把0.abc转化成分数即可。*/
其他人的方法是:比如0.(m),有:0.(m)= m*0.1+m*0.01+m*。。。。然后用等比数列求和公式化成分数形式,感觉这种方法稍稍复杂一点, 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值