【杭电oj】1717 - 小数化分数2(小数化分数,GCD)

小数化分数2

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4076    Accepted Submission(s): 1663


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

 

 

这道题没有整数部分,也就是说数组直接从a[2]开始后面是小数,我把这道题分为了三类:

①普通有限小数

②纯循环小数

③混循环小数

下面就挨个说它的转化方法:

①这一类很简单,分子就是小数点后面的数,分母就是10的n次方(n为小数点后面位数)

②这个小学学奥数的时候老师讲过,也不是很难:分子是循环的数,分母就是和它位数相同的9,比如0.(14),那么就是14/99

③这个就比上面的多了一步,我也是查了百度百科才知道的。下面就直接用百度百科的例子说明吧,仔细看看就发现方法了:

0.0105˙717˙=(105717-105)/9990000=105612/9990000=8801/832500

0.0˙869˙=869/9990,0.00˙716˙=716/99900=179/24975

0.368˙616˙=(368616-368)/999000=368248/999000=46031/124875

观察一下,就是小数部分减去不循环部分作为分母,分母就是循环部分个9和非循环部分个0组成,也许这么说很迷,还是看上面例子吧。

 

 

上面的步骤找到了分子分母,由GCD求最大公约数,约分一下即可。

 

代码如下:

#include <stdio.h>
#include <string.h>
int GCD(int a,int b)
{
	if (a%b==0)
		return b;
	int t;
	t=a%b;
	GCD(b,t);
}
int main()
{
	int u;
	char a[22];
	int dot,n;		//是否有循环小数,1为有 。有的话第x位开始循环 
	int l;
	int x,y,m;		//分子和分母 。位数。 
	int g;		//最小公倍数 (约分用) 
	scanf ("%d",&u);
	while (u--)
	{
		scanf ("%s",a);
		dot=0;
		l=strlen(a);
		x=0;
		y=0;
		n=-1;
		for (int i=0;i<l;i++)
		{
			if (a[i]=='(')
			{
				dot=1;
				n=i;
			}
		}
		if (dot)
		{
			if (n!=2)		//混循环小数
			{
				//先把小数点后面所有数字算出来
				for (int i=2;i<l-1;i++)		 
				{
					if (i==n)		//读到'('时跳过 
						continue;
					x=x*10+a[i]-'0';
				}
				//再把不循环部分算出来
				int t=0;
				for (int i=2;i<n;i++)
				{
					t=t*10+a[i]-'0';
				}
				x-=t;		//分子已求出 
				//再求分母
				for (int i=1;i<=l-n-2;i++)
				{
					y=y*10+9;
				}
				for (int i=1;i<=n-2;i++)
				{
					y*=10;
				}
			}
			else		//纯循环小数 
			{
				for (int i=n+1;i<l-1;i++)
				{
					x=x*10+a[i]-'0';
					y=y*10+9;
				}
			}
		}
		else		//有限小数 
		{
			y=1;
			for (int i=2;i<l;i++)
			{
				x=x*10+a[i]-'0';
				y=y*10;
			}
		}
		//约分
		g=GCD(x,y);
		x/=g;
		y/=g;
		printf ("%d/%d\n",x,y);
	}
	return 0;
}

杭州电子科技大学在线评测系统(杭电OJ)中的题目1000-1100是一系列编程题,我将分别进行回答。 1000题是一个简单的入门题,要求计算两个整数的和。我们可以使用一个简单的算法,读取输入的两个整数,然后将它们相加,最后输出结果即可。 1001题是一个稍微复杂一些的题目,要求实现字符串的逆序输出。我们可以使用一个循环来逐个读取输入的字符,然后将这些字符存储在一个数组中。最后,我们可以倒序遍历数组并将字符依次输出,实现字符串的逆序输出。 1002题是一个求最大公约数的问题。我们可以使用辗转相除法来解决,即先求出两个数的余数,然后将被除数更新为除数,将除数更新为余数,直至两个数的余数为0。最后的被除数就是最大公约数。 1003题是一个比较简单的排序问题。我们可以使用冒泡排序算法来解决,即每次比较相邻的两个元素,如果它们的顺序错误就交换它们的位置。重复这个过程直至整个数组有序。 1100题是一个动态规划问题,要求计算给定序列中的最长上升子序列的长度。我们可以使用一个数组dp来保存到达每个位置的最长上升子序列的长度。每当遍历到一个位置时,我们可以将其和之前的位置比较,如果比之前位置的值大,则将其更新为之前位置的值加1,最后返回dp数组的最大值即可。 以上是对杭电OJ1000-1100题目的简要回答,涉及了一些基本的编程知识和算法思想。希望对您有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值