版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cugsl/article/details/81909069
题意
给一个小于1大于0的无限循环小数,将其化成分数,输出分母最小的情况。
分析
首先题目给定了数字最长是9位,组成是0.abcde…这样的形式,所以可以直接读取中间的数字并用ll存起来。然后遍历9种循环情况,分别求出他们的分数形式。下面说下如何化成分数。
隐约记得这个是小学课本上的东西,首先将这个数乘pow(10,循环节的长度),然后减去这个整数,举个例子,0.923333…这里我们假设3是循环节,那么乘以10,得到9.233下发现后面的循环的3都被减去了,那么只剩下9.23和0.92。同理假设循环节是23,那么就乘上100,得到92.3232323…另一个还是0.92323,对比一下发现后面的23也都减去了,剩下也只剩92.3-0.9。但是小数不好处理,所以我们直接用整数处理以后再化成小数。首先我们得到的是整个数字部分的整数,然后遍历每个循环节,假设循环节是后1位,后两位…后i位..这样循环节的长度就是i,所以先乘以的数就是pow(10,i)然后再减去这个数。因为先乘了pow(10,i),又减去了1,所以最后还要除pow(10,i)-1.然后分子和分母单独看,求个gcd,遍历每种循环节情况,输出最小分母的那一种。
这里有个细节问题,因为我们处理的时候是整数,但实际上应该是小数,所以再做除法的时候要分母不一定是上述的pow(10,i),还需要乘上一个倍数。具体看代码
代码
#include <iostream>
#include <string>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long int ll;
ll gcd(ll a, ll b)
{
if (a > b) swap(a, b);
if (a == 0) return b;
else return gcd(b%a, a);
}
int main()
{
ios::sync_with_stdio(false);
string a;
while (cin >> a&&a!="0")
{
ll all = 0;
for (int i = 2; a[i] != '.'; i++)
{
all += a[i] - '0';
all = all * 10;
}
all = all / 10;
int len = a.size() - 5;
ll up, down, g, mu = 100000000000, md = 100000000000;
for (int i = 1; i <= len; i++)
{
up = all - all / (ll)pow(10.0, i);
down = ((ll)pow(10.0, i) - 1)*(ll)pow(10.0, len - i);
g = gcd(up, down);
if (down / g < md) { md = down / g; mu = up / g; }
}
cout << mu << "/" << md << endl;
}
}