Description
Ray 在数学课上听老师说,任何小数都能表示成分数的形式,他开始了化了起来,很快他就完成了,但他又想到一个问题,如何把一个循环小数化成分数呢?
请你写一个程序不但可以将普通小数化成最简分数,也可以把循环小数化成最简分数。
请你写一个程序不但可以将普通小数化成最简分数,也可以把循环小数化成最简分数。
Input
第一行是一个整数N,表示有多少组数据。
每组数据只有一个纯小数,也就是整数部分为0。小数的位数不超过9位,循环部分用()括起来。
每组数据只有一个纯小数,也就是整数部分为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*。。。。然后用等比数列求和公式化成分数形式,感觉这种方法稍稍复杂一点,