小数化分数2
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2606 Accepted Submission(s): 1060
Problem 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
讲解:本题涉及到小数与分数的转化问题,具体分成三类情况讨论:
(1)当小数为有限不循环小数时,直接将小数部分提取出来,化成整数,并将其与pow(10,l)进行gcd(a,b)化简即可(l为小数部分的长度);
(2)当小数为无限循环小数且第一位即为循环节时,直接将小数部分提取出来,化成整数,并将其与pow(10,l)-1进行gcd(a,b)化简即可(l为小数部分的长度);
(3)当小数为无限循环小数且第一位不为循环节时,将不是循环节的小数部分提取出来记作a,将循环节提取出来记作b,将 a*pow(10,l2)+b-a 与 (pow(10,l2)-1)*pow(10,l1)进行gcd(a,b)化简即可(l1为小数部分非循环节的长度,l2为小数部分循环节的长度);
*证明过程略,请尽量不要使用pow函数,其参数为double类型,做这种题容易损失精度。
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
//全题请不要使用long long,用int就能过,用long long反而过不了,可能是oj中long long使用问题
int gcd(int a,int b)
{
int r=a%b;
while(r)
{
a=b;
b=r;
r=a%b;
}
return b;
}
void work(char s[])
{
int l1=0,l2=0;
int L=strlen(s);
int a=0,b=0;
int i;
bool flag=false;
for(i=2;i<L;i++)
{
if(s[i]=='(')
{
flag=true;
break;
}
l1++;
a=a*10+s[i]-'0';
}
if(flag)
for(i+=1;i<L-1;i++)
{
b=b*10+s[i]-'0';
l2++;
}
int r,t=1;
if(!flag)
{
for(t=1,i=1;i<=l1;i++)
t=t*10;
r=gcd(a,t);
printf("%d/%d\n",a/r,t/r);
//printf("%lld %lld\n",a,t);
}
else
{
for(t=1,i=1;i<=l2;i++)
t*=10;
a=a*t+b-a;
t--;b=t;
for(t=1,i=1;i<=l1;i++)
t*=10;
b*=t;
r=gcd(a,b);
printf("%d/%d\n",a/r,b/r);
//printf("%lld %lld\n",a,b);
}
}
int main()
{
int n;
scanf("%d",&n);
char s[20];
while(n--)
{
scanf("%s",s);
work(s);
}
return 0;
}