HDU 2.1.8 小数化分数2

Problem Description
Ray 在数学课上听老师说,任何小数都能表示成分数的形式,他开始了化了起来,很快他就完成了,但他又想到一个问题,如何把一个循环小数化成分数呢?
请你写一个程序不但可以将普通小数化成最简分数,也可以把循环小数化成最简分数。
 
Input
第一行是一个整数N,表示有多少组数据。
每组数据只有一个纯小数,也就是整数部分为0。小数的位数不超过9位,循环部分用()括起来。
 
Output
对每一个对应的小数化成最简分数后输出,占一行。
 
Sample Input
3
0.(4)
0.5
0.32(692307)
 
Sample Output
4/9
1/2
17/52
 
 
Source
2007省赛集训队练习赛(2)
 
Recommend
lcy
 

#include<stdio.h>
#include"algorithm"
using namespace std;
unsigned long long gcd(unsigned long long a, unsigned long long b)
{
	return b == 0 ? a : gcd(b,a%b);
}
int main()
{
	//freopen("f://in.txt", "r", stdin);
	int testCase;
	char inNum[20];
	scanf("%d", &testCase);
	getchar();
	while (testCase--)
	{
		memset(inNum, 0, sizeof(inNum));
		int len = 0, leftBracket = 0, rightBracket=0;
		scanf("%s", inNum);
		while (1)
		{
			if (inNum[len] == '\0')break;
			if (inNum[len] == '(')leftBracket = len;
			if (inNum[len] == ')')rightBracket = len;
			len++;
		}
		if (len == 0)
			break;
		unsigned long long numerator = 0, denominator,gcdND;
		if (leftBracket == 0)//纯小数
		{
			for (int i = 0; i < len - 2; i++)
				numerator += unsigned long long(round((int(inNum[i + 2]) - '0')*pow(10, (len - 3 - i))+0.000001));
			denominator = unsigned long long(round(pow(10, (len - 2)) + 0.000001));
		}
		if (leftBracket == 2)//纯循环小数
		{
			int bracketLen = rightBracket - leftBracket - 1;
			for (int i = 0; i < bracketLen; i++)
				numerator += unsigned long long(round((int(inNum[i + 3]) - '0')*pow(10, (bracketLen - 1 - i)) + 0.000001));
			denominator = unsigned long long(round(pow(10, bracketLen) - 1 + 0.000001));
		}
		if (leftBracket > 2)//部分循环小数
		{
			int bracketLen = rightBracket - leftBracket - 1;
			int outLen = leftBracket - 2;
			for (int i = 0; i < outLen; i++)
				numerator += unsigned long long(round((int(inNum[i + 2]) - '0')*pow(10, (bracketLen + outLen - 1 - i)) + 0.000001));
			for (int i = 0; i < bracketLen; i++)
				numerator += unsigned long long(round((int(inNum[i + 3 + outLen]) - 48)*pow(10, (bracketLen - 1 - i)) + 0.000001));
			for (int i = 0; i < outLen; i++)
				numerator -= unsigned long long(round((int(inNum[i + 2]) - 48)*pow(10, (outLen - 1 - i)) + 0.000001));
			denominator = unsigned long long(round(pow(10, (bracketLen + outLen)) - pow(10, outLen) + 0.000001));
		}
		gcdND = gcd(denominator, numerator);
		printf("%lld/%lld\n", numerator / gcdND, denominator / gcdND);
	}
	return 0;
}


【思路】

不循环的小数,如0.12345,可以表示为12345/100000,约分即可。
循环小数x,可以通过  x*10^a-x*10^b=整数n   ->   x= n/(10^a-10^b)
至于怎么取a和b使得结果n为整数看如下例子:


⑴  0.(123):

括号有几位,a就取几;b取0。
0.(123)*10^3=123.123123...
0.(123)*10^0=    0.123123...
10^3*0.(123)-10^0*0.(123)=123
0.(123)=123/(10^3-10^0)=123/999=41/333


(2)  0.45(678)

小数后有几位,a就取几;括号有几位,b就取几。

0.45(678)*10^5=45678.678678...

0.45(678)*10^2=45.678678...

0.45(678)*10^5-0.45(678)*10^2=45633

0.45(678)=45633/(10^5-10^2)=45633/99900


求得一个未化简的分数后,可以求分子分母的最大公约数,分子分母分别除以最大公约数即为最简分数

<strong style="font-size: 18px;">
</strong>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值