杭电oj HDOJ 1717 小数化分数2

杭电oj HDOJ 1717 小数化分数2

Problem Description

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

Input

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

Output

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

解题思路

循环小数分为纯循环小数混循环小数
纯循环小数是指小数点后都是循环节的循环小数
混循环小数是指并非小数点后都是循环节的循环小数

本题考察的是把普通小数纯循环小数混循环小数三种情况的小数化成分数。

  1. 纯循环小数的变化原则:循环节有几位就在分母上添几个9,并将循环节添在分子上
  2. 混循环小数的变化原则:循环节有几位,就在分母上先添几个9,小数部分不循环的小数有几位,就在9后面添几个0,分子用所有的小数部分减去非循环节的小数部分

本人的C++解决方案

#include <iostream>
#include <string>
#include <sstream>
using namespace std;

int gcd(int, int);					// 辗转相除法求最大公约数
void pure(int, int);				// 纯循环小数处理函数
void mix(int, int, int);			// 混循环小数处理函数

int main()
{
	int N, i, count, len, numer, denomin, j, num1, num2;
	int pos_point, pos_left, pos_right;
	string str, s1, s2;
	stringstream ss1, ss2;
	cin >> N;
	for (i = 0; i < N; i++) {
		cin >> str;
		len = str.length();
		pos_left = str.find('(');
		pos_point = str.find('.');
		denomin = 1;
		// 循环小数
		if (pos_left != string::npos) {
			pos_right = str.find(')');
			count = pos_right - pos_left - 1;		// 循环节长度
			// 循环节的数作分子
			s1 = str.substr(pos_left + 1, count);
			if (pos_left == pos_point + 1) {
				ss1 << s1;
				ss1 >> numer;			// 循环的小数,字符串变整数
				pure(numer, count);
			}
			else {
				num1 = pos_left - pos_point - 1;
				s2 = str.substr(pos_point + 1, num1);
				ss1 << s2 + s1;
				ss1 >> numer;			// 所有的小数,字符串变整数
				ss2 << s2;
				ss2 >> num2;		// 非循环节的小数,字符串变整数
				// 分子用所有的小数部分减去非循环节的小数部分
				mix(numer - num2, num1, count);
				ss2.clear();
			}
		}
		// 普通小数
		else {
			count = len - pos_point - 1;		// 小数点后长度
			// 小数点后有几位,分母中就有几个0
			for (j = 0; j < count; j++) {
				denomin *= 10;
			}
			// 小数点后的数作分子
			s1 = str.substr(pos_point + 1, count);
			ss1 << s1;
			ss1 >> numer;
			cout << numer / gcd(numer, denomin) << '/' << denomin /gcd(numer, denomin) << endl;
		}
		ss1.clear();
	}
	return 0;
}

int gcd(int n, int m) {
	int temp;
	temp = n % m;
	while (temp != 0) {
		n = m;
		m = temp;
		temp = n % m;
	}
	return m;
}

void pure(int n, int c)
{
	int i = 0, temp = 0;
	// 循环节有几位就在分母上添几个9
	for (; i < c; i++) {
		temp = temp * 10 + 9;
	}
	cout << n / gcd(n, temp) << '/' << temp / gcd(n, temp) << endl;
}

void mix(int n, int m, int c)
{
	int i = 0, temp1 = 0, temp2 = 1, temp;
	// 循环节有几位,就在分母上先添几个9
	for (; i < c; i++) {
		temp1 = temp1 * 10 + 9;
	}
	// 小数部分不循环的小数有几位,就在9后面添几个0
	for (i = 0; i < m; i++) {
		temp2 *= 10;
	}
	temp = temp1 * temp2;
	cout << n / gcd(n, temp) << '/' << temp / gcd(n, temp) << endl;
}

代码通过HDOJ平台运行检查,如发现错误,欢迎指出和纠正,谢谢!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值