杭电oj HDOJ 1717 小数化分数2
Problem Description
Ray 在数学课上听老师说,任何小数都能表示成分数的形式,他开始了化了起来,很快他就完成了,但他又想到一个问题,如何把一个循环小数化成分数呢?
请你写一个程序不但可以将普通小数化成最简分数,也可以把循环小数化成最简分数。
Input
第一行是一个整数N,表示有多少组数据。
每组数据只有一个纯小数,也就是整数部分为0。小数的位数不超过9位,循环部分用()括起来。
Output
对每一个对应的小数化成最简分数后输出,占一行。
解题思路
循环小数分为纯循环小数和混循环小数。
纯循环小数是指小数点后都是循环节的循环小数。
混循环小数是指并非小数点后都是循环节的循环小数。
本题考察的是把普通小数、纯循环小数和混循环小数三种情况的小数化成分数。
- 纯循环小数的变化原则:循环节有几位就在分母上添几个9,并将循环节添在分子上。
- 混循环小数的变化原则:循环节有几位,就在分母上先添几个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平台运行检查,如发现错误,欢迎指出和纠正,谢谢!