洛谷P1572题解:分数运算的奥秘,新手也能看懂的超详细教程
二、详细技术讲解
1. 分数表示与运算
我们使用一个简单的结构体Fraction
来表示分数,包含分子和分母两个成员变量。结构体中实现了两个关键方法:
simplify()
: 用于化简分数,通过计算分子分母的最大公约数,并将分数化为最简形式operator+
: 重载加法运算符,实现分数的加法运算
2. 字符串解析
解析输入字符串是本题的关键难点。我们需要处理以下几种情况:
正负号的处理:每个分数可能有自己的正负号
分子和分母的分离:通过'/'字符分隔
运算符的识别:'+'或'-'符号
解析过程采用逐个字符扫描的方式:
首先处理可能的符号位
然后读取数字部分作为分子
如果遇到'/',则继续读取分母
否则视为整数(分母为1)
最后记录运算符
3. 计算过程
计算过程相对简单:
初始化结果为第一个分数
根据运算符决定后续分数是加还是减
逐个进行分数运算
每次运算后自动化简结果
4. 结果输出
最终结果需要根据分母是否为1决定输出形式:
分母为1:输出整数形式
否则:输出分数形式
三、完整代码
#include <iostream> #include <string> #include <vector> #include <algorithm> using namespace std; // 计算最大公约数 int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); } // 分数结构体 struct Fraction { int numerator; // 分子 int denominator; // 分母 // 化简分数 void simplify() { int common = gcd(abs(numerator), abs(denominator)); numerator /= common; denominator /= common; // 确保分母为正 if (denominator < 0) { numerator *= -1; denominator *= -1; } } // 分数加法 Fraction operator+(const Fraction& other) const { Fraction result; result.numerator = numerator * other.denominator + other.numerator * denominator; result.denominator = denominator * other.denominator; result.simplify(); return result; } }; int main() { string s; getline(cin, s); vector<Fraction> fractions; vector<char> operators; // 解析字符串 int i = 0; while (i < s.size()) { // 解析分子 int sign = 1; if (s[i] == '-') { sign = -1; i++; } else if (s[i] == '+') { i++; } int num = 0; while (i < s.size() && isdigit(s[i])) { num = num * 10 + (s[i] - '0'); i++; } num *= sign; // 解析分母 if (i < s.size() && s[i] == '/') { i++; int den = 0; while (i < s.size() && isdigit(s[i])) { den = den * 10 + (s[i] - '0'); i++; } fractions.push_back({num, den}); } else { // 整数视为分母为1的分数 fractions.push_back({num, 1}); } // 记录运算符 if (i < s.size() && (s[i] == '+' || s[i] == '-')) { operators.push_back(s[i]); i++; } } // 计算结果 Fraction result = fractions[0]; for (int j = 0; j < operators.size(); j++) { Fraction next = fractions[j + 1]; if (operators[j] == '-') { next.numerator *= -1; } result = result + next; } // 输出结果 if (result.denominator == 1) { cout << result.numerator << endl; } else { cout << result.numerator << "/" << result.denominator << endl; } return 0; }
四、常见问题解答
Q: 如何处理连续的运算符?
A: 题目保证输入合法,不会出现连续的运算符。
Q: 如何处理分母为0的情况?
A: 题目保证输入合法,不会出现分母为0的情况。
Q: 为什么要在化简函数中处理分母的符号?
A: 这是为了统一分数的表示形式,确保分母始终为正数,便于比较和后续处理。
五、扩展思考
如何扩展支持乘除法运算?
如何处理带括号的表达式?
如何支持混合数(如3又1/2)的输入?
六、总结
通过这道题目,我们学习了:
字符串解析的技巧
分数运算的原理
运算符重载的应用
代码结构化的设计方法
掌握这些基础知识对于解决更复杂的计算问题至关重要。
原创内容 转载请注明出处