题意:给你一个小数,求他的分数形式。
思路:
这题主要是给出一个无限循环小数,要求去求他所对应的具有最小分母的分数。无限循环小数转换为分数有
一定的规律和方法可循:
(1)假设输入小数为0.i1 i2 ... it j1 j2 ... jk,即j1 j2 ... jk是循环的部分 那么这个分数可以分两部分来计算即不循环的部分和循环的部分.
(2)先来看不循环的部分,这个非常简单.即为 i1i2 ... it / 10 ^ t,即不循环部分的分子分母分别为: upd = i1 i2 ... it; downd = 10 ^ t;
(3)再来看循环部分,这部分有点难.在数论中的典型做法是:
取分子up为:j1 j2 ... jk
分母down为: 10 ^ (t + k) - 10 ^ t
(4)那么最后所得的分数即为: upd / downd + up / down = (upd * down + downd * up) / (down * up)
(5)注意计算的时候要约分.另外由于题目没有明确给出循环部分的长度,所以需要自己枚举,然后计算出
所有的分数取分母最小的.另外要注意的是输入中含有全0的情况(输出0/1),这个太恶心了,因为题目明确说
了输入不全为0的,害我WA了好几次.
#include <iostream>
#include <cmath>
#include <cstring>
using namespace std;
char input[20];
int spos, epos;
__int64 minup, mindown;
__int64 gcd(__int64 a, __int64 b)
{
if(b == 0) return a;
else return gcd(b, a % b);
}
//利用最大公约数来约分
void trim(__int64 &up, __int64 &down)
{
__int64 gcdval;
while((gcdval = gcd(up, down)) != 1)
{
up /= gcdval;
down /= gcdval;
}
}
//判断是否全0
bool allZero()
{
for(int i = strlen(input) - 4; i >= 2; i--)
if(input[i] != '0') return false;
return true;
}
int main()
{
while(scanf("%s", input) && strcmp(input, "0") != 0)
{
//当不全0时
if(!allZero())
{
mindown = -1;
epos = strlen(input) - 4; //输入字符串数字位的结束位置
spos = 2; //小数点后面的起始位置
__int64 up = 0, down = 0, upd = 0, downd = 0, dupdown;
//枚举循环部分的起始位置
for(int t = spos; t <= epos; t++)
{
upd = up = 0;
int k = spos;
while(k < t && input[k] == '0') k++; //找到非循环部分第一个不为0的位置
for(; k <= epos; k++)
{
if(k < t) upd = upd * 10 + int(input[k] - '0'); //统计非循环部分的分子值
if(k >= t) up = up * 10 + int(input[k] - '0'); //统计循环部分的分子值
}
downd = pow(10.0, t - spos); //非循环部分的分母值
down = pow(10.0, epos - spos + 1); //所有小数部分的分母值
dupdown = pow(10.0, epos - t + 1); //循环部分的分母值
down = down - down / dupdown; //制造循环部分小数的最终分母值
if(up != 0) trim(up, down); //约分
if(upd != 0) trim(upd, downd); //约分
__int64 newup, newdown;
newup = up * downd + down * upd;
newdown = down * downd;
if(newup != 0) trim(newup, newdown); //计算最终结果
if(mindown == -1 || newdown < mindown) //取分母最小的
{
mindown = newdown;
minup = newup;
}
}
printf("%I64d/%I64d/n", minup, mindown);
}
//全为0的情况
else printf("0/1/n");
}
return 0;
}