小数化分数c++(附做法数学证明)

小数化分数

时间限制(普通/Java):1000MS/10000MS 内存限制:65536KByte

描述

在数学课上听老师说,任何小数都能表示成分数的形式,他开始了化了起来,很快他就完成了,但他又想到一个问题,如何把一个循环小数化成分数呢?
请你写一个程序不但可以将普通小数化成最简分数,也可以把循环小数化成最简分数。

输入

第一行是一个整数N,表示有多少组数据。
每组数据只有一个纯小数,也就是整数部分为0。小数的位数不超过9位,循环部分用()括起来。

输出

对每一个对应的小数化成最简分数后输出,占一行。

样例输入

3
0.(4)
0.5
0.32(692307)

样例输出

4/9
1/2
17/52

 

思路:1.对于普通不包含循环体的小数(其中有无限不循环小数), 其化为分数都是让小数点后组成的数除以10的此数的位数次方,比如0.1234=1234/10000。

          2.对于含有循环体的小数,将循环体单独取出,计算出位数,有几位,则分母中就包含几个9,如果小数部分非循环体部分还有数,有几个数就在分母后面加几个零。例如例子中的 0.32(692307),分母就为99999900,循环体有6位所以分母有6个9,小数部分非循环体有两位数,则分母再加两个零。分子则是由循环体减去非循环体,例如:0.32(692307),分子为32692307-32
 

证明:对于一个数0.32(692307)

=\frac{32}{100}+\frac{692307}{1000000}+...... =\frac{32}{100}+\frac{1}{100}*(\frac{692307}{1000000}+\frac{692307}{1000000^{2}}+......) =\frac{32}{100}+\frac{692307}{100}\sum_{i=1}^{+\infty } \frac{1}{1000000^{i}} =\frac{32}{100}+\frac{692307}{100}*(\frac{1}{999999})=\frac{32*999999+692307}{99999900}

\sum_{i=1}^{+\infty } \frac{1}{a^{x}} =\sum_{i=1}^{+\infty }\frac{\frac{1}{a}(1-\frac{1}{a^{n}}))}{1-\frac{1}{a}}=\lim_{n->+\infty }(\frac{\frac{1}{a}(1-\frac{1}{a^{n}}))}{1-\frac{1}{a}})

\because \lim_{i->+\infty }\frac{1}{a^{i}}=0

\therefore =\lim_{n->+\infty }(\frac{\frac{1}{a}}{1-\frac{1}{a}}) =\frac{1}{a-1}

注意不要用pow有精度问题答案可能被卡掉,最后附上代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 60;
ll gcd(ll a, ll b)
{
	if (b == 0)return a;
	return gcd(b, a % b);
}
ll poww(ll x,ll y)
{
	ll s = 1;
	for (int i = 0; i < y; i++)
		s *= x;
	return s;
}
int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		string x;
		cin >> x;
		int n = x.size();
		int flag = 0;
		ll t1, t2, t3, t4, t5,s1,s2,s3,s4,s5;
		t1 = t2 = t3 = t4 = t5 = 0;
		s1 = s2 = s3 = s4 = s5 = 0;
		for (int i = 2; i < n; i++)
		{
			if (x[i] == '(' || x[i] == ')')
				flag = 1;
			 if (flag == 0)
			{
				t4 = t4 * 10 + x[i] - 48;
				s1++;
			}
			if (flag == 1 &&x[i] >= '0' &&x[i] <= '9') s2++;
			if (x[i] >= '0' && x[i] <= '9')t3 = t3 * 10 + x[i] - 48;
		}
		if (flag == 0)
		{
			for (int i = 2; i < n; i++)
				t1 = t1 * 10 + x[i] - 48;
			t2 = poww(10, n - 2);
			if (t1 > t2)t5 = gcd(t1, t2);
			else t5= gcd(t2, t1);
			cout << t1 / t5 << "/" << t2 / t5 << endl;
		}
		else
		{
			t1 = t3- t4;
			for (int i = 0; i < s2; i++)
				t2 = t2 * 10 + 9;
			t2 = t2 * poww(10, s1);
			if (t1 > t2)t5 = gcd(t1, t2);
			else t5 = gcd(t2, t1);
			cout << t1 / t5 << "/" << t2 / t5 << endl;
		}
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值