Ray在数学课上听老师讲解,得知任何小数都可以表示成分数的形式。他尝试将普通小数转换为分数,并很快完成了任务。然而,他又提出了一个新的问题:如何将循环小数转换为最简分数?本文将介绍一种算法,不仅能将普通小数转换为最简分数,还能处理循环小数。
### 问题描述
给定一个纯小数(即整数部分为0),需要将其转换为最简分数。小数的位数不超过9位,循环部分用括号表示。
### 输入格式
输入的第一行是一个整数N,表示有N组数据。每组数据包含一个纯小数,小数的位数不超过9位,循环部分用括号表示。
### 输出格式
对于每一组数据,输出其对应的最简分数,每组数据占一行。
### 示例
输入:
3
0.(4)
0.5
0.32(692307)
输出:
4/9
1/2
17/52
### 算法思路
1. **普通小数**:直接将小数转换为分数,然后通过最大公约数(GCD)化简。
2. **循环小数**:将小数分为非循环部分和循环部分。分母由循环部分的位数决定,每有一位循环部分,分母就多一个9;每有一位非循环部分,分母就多一个0。分子则由非循环部分加上循环部分的值减去非循环部分的值。
### 代码实现
#include
#include
#include
using namespace std;
int Gcd(int x, int y) {
while (y) {
int temp = y;
y = x % y;
x = temp;
}
return x;
}
void ConvertToFraction(char *s) {
int len = strlen(s);
int nOnRepeating= 0, repeating = 0;
int numerator = 0, denominator = 0;
bool isRepeating = false;
for (int i = 2; i if (s[i] == '(') {
isRepeating = true;
break;
}
nOnRepeating= nonRepeating * 10 + (s[i] - '0');
}
for (int i = 2; i if (s[i] == '(' || s[i] == ')') continue;
repeating = repeating * 10 + (s[i] - '0');
}
if (!isRepeating) {
denominator = 1;
for (int i = 0; i denominator *= 10;
}
numerator = repeating;
} else {
int nOnRepeatingLen= strlen(s) - 2 - (len - s[i] - 1);
int repeatingLen = len - s[i] - 2;
denominator = 0;
for (int i = 0; i denominator = denominator * 10 + 9;
}
for (int i = 0; i denominator *= 10;
}
numerator = repeating - nonRepeating;
}
int gcd = Gcd(numerator, denominator);
printf("%d/%d\n", numerator / gcd, denominator / gcd);
}
int main() {
int N;
scanf("%d", &N);
while (N--) {
char s[20];
scanf("%s", s);
ConvertToFraction(s);
}
return 0;
}