小数化分数2
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4076 Accepted Submission(s): 1663
请你写一个程序不但可以将普通小数化成最简分数,也可以把循环小数化成最简分数。
每组数据只有一个纯小数,也就是整数部分为0。小数的位数不超过9位,循环部分用()括起来。
3 0.(4) 0.5 0.32(692307)
4/9 1/2 17/52
这道题没有整数部分,也就是说数组直接从a[2]开始后面是小数,我把这道题分为了三类:
①普通有限小数
②纯循环小数
③混循环小数
下面就挨个说它的转化方法:
①这一类很简单,分子就是小数点后面的数,分母就是10的n次方(n为小数点后面位数)
②这个小学学奥数的时候老师讲过,也不是很难:分子是循环的数,分母就是和它位数相同的9,比如0.(14),那么就是14/99
③这个就比上面的多了一步,我也是查了百度百科才知道的。下面就直接用百度百科的例子说明吧,仔细看看就发现方法了:
0.0105˙717˙=(105717-105)/9990000=105612/9990000=8801/832500
0.0˙869˙=869/9990,0.00˙716˙=716/99900=179/24975
0.368˙616˙=(368616-368)/999000=368248/999000=46031/124875
观察一下,就是小数部分减去不循环部分作为分母,分母就是循环部分个9和非循环部分个0组成,也许这么说很迷,还是看上面例子吧。
上面的步骤找到了分子分母,由GCD求最大公约数,约分一下即可。
代码如下:
#include <stdio.h>
#include <string.h>
int GCD(int a,int b)
{
if (a%b==0)
return b;
int t;
t=a%b;
GCD(b,t);
}
int main()
{
int u;
char a[22];
int dot,n; //是否有循环小数,1为有 。有的话第x位开始循环
int l;
int x,y,m; //分子和分母 。位数。
int g; //最小公倍数 (约分用)
scanf ("%d",&u);
while (u--)
{
scanf ("%s",a);
dot=0;
l=strlen(a);
x=0;
y=0;
n=-1;
for (int i=0;i<l;i++)
{
if (a[i]=='(')
{
dot=1;
n=i;
}
}
if (dot)
{
if (n!=2) //混循环小数
{
//先把小数点后面所有数字算出来
for (int i=2;i<l-1;i++)
{
if (i==n) //读到'('时跳过
continue;
x=x*10+a[i]-'0';
}
//再把不循环部分算出来
int t=0;
for (int i=2;i<n;i++)
{
t=t*10+a[i]-'0';
}
x-=t; //分子已求出
//再求分母
for (int i=1;i<=l-n-2;i++)
{
y=y*10+9;
}
for (int i=1;i<=n-2;i++)
{
y*=10;
}
}
else //纯循环小数
{
for (int i=n+1;i<l-1;i++)
{
x=x*10+a[i]-'0';
y=y*10+9;
}
}
}
else //有限小数
{
y=1;
for (int i=2;i<l;i++)
{
x=x*10+a[i]-'0';
y=y*10;
}
}
//约分
g=GCD(x,y);
x/=g;
y/=g;
printf ("%d/%d\n",x,y);
}
return 0;
}