HDU 1717 小数化分数2
Problem Description
Ray 在数学课上听老师说,任何小数都能表示成分数的形式,他开始了化了起来,很快他就完成了,但他又想到一个问题,如何把一个循环小数化成分数呢?
请你写一个程序不但可以将普通小数化成最简分数,也可以把循环小数化成最简分数。
请你写一个程序不但可以将普通小数化成最简分数,也可以把循环小数化成最简分数。
Input
第一行是一个整数N,表示有多少组数据。
每组数据只有一个纯小数,也就是整数部分为0。小数的位数不超过9位,循环部分用()括起来。
每组数据只有一个纯小数,也就是整数部分为0。小数的位数不超过9位,循环部分用()括起来。
Output
对每一个对应的小数化成最简分数后输出,占一行。
Sample Input
3 0.(4) 0.5 0.32(692307)
Sample Output
【思路分析】
该题的关键点就是循环小数化为分数,有一个结论,假如这个循环小数是0.(1234),其化为分数即为1234/9999,也就是循环的部分除以这个循环部分长度个9,即1234除以4个(1234的长度)9。证明如下:
设这个循环小数x为0.(yyy),将这个x乘以10的循环长度的次方,即10^3,得到yyy.(yyy),从而可以得出下列等式:
x*10^3 - x = yyy => x(10^3 - 1) = yyy => x = yyy/999。其他长度同理可证。
有了以上的结论便可以将循环小数化为分数。然后由gcd求出最大公约数对分数化简。
还有一点需要注意的就是这个小数包括不循环小数和循环小数两个部分,则需要分别对这两个部分化为分数,然后再相加、通分、合并、化简。这个过程需要注意通分后的数据范围,由于小数位数最长为9,所以通分时int会存不下这个结果,因此需要用long long 或者_int64 的变量来存结果,否则会报WA。
代码如下:
4/9
1/2
17/52
【思路分析】
该题的关键点就是循环小数化为分数,有一个结论,假如这个循环小数是0.(1234),其化为分数即为1234/9999,也就是循环的部分除以这个循环部分长度个9,即1234除以4个(1234的长度)9。证明如下:
设这个循环小数x为0.(yyy),将这个x乘以10的循环长度的次方,即10^3,得到yyy.(yyy),从而可以得出下列等式:
x*10^3 - x = yyy => x(10^3 - 1) = yyy => x = yyy/999。其他长度同理可证。
有了以上的结论便可以将循环小数化为分数。然后由gcd求出最大公约数对分数化简。
还有一点需要注意的就是这个小数包括不循环小数和循环小数两个部分,则需要分别对这两个部分化为分数,然后再相加、通分、合并、化简。这个过程需要注意通分后的数据范围,由于小数位数最长为9,所以通分时int会存不下这个结果,因此需要用long long 或者_int64 的变量来存结果,否则会报WA。
代码如下:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
__int64 gcd(__int64 a,__int64 b)
{
__int64 r = 1;
while (r > 0)
{
r = a % b;
a = b;
b = r;
}
return a;
}
int main()
{
int n;
scanf("%d",&n);
while(n--)
{
char num[20];
scanf("%s",num);
int len = strlen(num);
int i;
__int64 a = 0,b = 0;//a记录不循环的小数部分,b记录循环的小数部分
int lenofA = 0,lenofB = 0;//a的长度和b的长度
__int64 div1 = 1,div2 = 0;//不循环小数和循环小数的对应的分母
for(i = 2;i < len;i++)//存取不循环小数
{
if(num[i] != '(')
{
a *= 10;
a += num[i] - '0';
lenofA++;
div1 *= 10;
}
if(num[i] == '(')
break;
}
i++;
while(i < len)//存取循环小数
{
if(num[i] != ')')
{
b *= 10;
b += num[i] - '0';
lenofB++;
div2 *= 10;
div2 += 9;
}
i++;
}
if(lenofA != 0)
div2 *= div1;
int gcd1,gcd2;
if(a == 0 && b != 0)//不存在不循环小数部分
{
gcd2 = gcd(b,div2);
b /= gcd2;
div2 /= gcd2;
printf("%I64d/%I64d\n",b,div2);
}
if(b == 0 && a != 0)//不存在循环小数部分
{
gcd1 = gcd(a,div1);
a /= gcd1;
div1 /= gcd1;
printf("%I64d/%I64d\n",a,div1);
}
if(a != 0 && b != 0)
{
gcd1 = gcd(a,div1);
gcd2 = gcd(b,div2);
a /= gcd1;
div1 /= gcd1;
b /= gcd2;
div2 /= gcd2;
__int64 top = a * div2 + b * div1;
__int64 down = div1 * div2;
__int64 gcd3 = gcd(top,down);
top /= gcd3;
down /= gcd3;
printf("%I64d/%I64d\n",top,down);
}
}
return 0;
}
本文介绍了一种将循环小数转化为最简分数的方法,并详细解释了算法背后的数学原理。通过实例演示了如何处理不循环小数和循环小数,并强调了通分时的数据范围限制,以避免WA错误。
&spm=1001.2101.3001.5002&articleId=47110917&d=1&t=3&u=8f3e78e5f945442c8fe589e43f75459e)
5521

被折叠的 条评论
为什么被折叠?



