华为OD机试 2024C卷题库疯狂收录中,刷题点这里
专栏导读
本专栏收录于《华为OD机试(JAVA)真题(A卷+B卷+C卷)》。
刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。
一、题目描述
给定一个表达式,求其分数计算结果
表达式的限制如下:
- 所有的输入数字皆为正整数(包括0)
- 仅支持四则运算(±*/)和括号
- 结果为整数或分数, 分数必须化为最简格式(比如6, 3/4, 7/8, 90/7)
- 除数可能为0,如果遇到这种情况,直接输出"ERROR"
- 输入和最终计算结果中的数字都不会超出整型范围
用例的输入一定合法, 不会出现括号不匹配的情况
二、输入描述
字符串格式的表达式,仅支持±*/,数字可能超过两位,可能带有空格,没有负数
长度小于200个字符
三、输出描述
表达式结果,以最简格式表达 如果结果为整数,那么直接输出整数 如果结果为分数,那么分子分母不可再约分,可以为假分数,不可表达为带分数 结果可能是负数, 负号放在最前面
1、输入
1 / (0-5)
2、输出
-1/5
四、解题思路
此问题需要处理一个包含四则运算和括号的数学表达式,并正确处理分数和除法。关键步骤如下:
1、解析和计算表达式:
使用递归或栈来处理括号和操作符的优先级。
支持整数和分数的四则运算。
2、处理分数:
对于每次运算结果,若为分数,则需要化简(约分)。
使用两个整数表示分数(分子和分母),并在每次运算后使用最大公约数(GCD)来约分。
3、错误处理:
当遇到除数为零的情况,立即返回"ERROR"。
4、表达式结果格式:
如果分母为1,则输出整数。
如果不为1,则输出最简分数格式。
确保分数的符号只出现在分子上。
五、Java算法源码
通过递归函数 eval() 来计算和解析包含括号的表达式。它支持基本的四则运算,并正确处理分数和整数。当除数为零时,它会捕获ArithmeticException并返回"ERROR"。
public class OdTest01 {public static void main(String[] args) {Scanner sc = new Scanner(System.in);String expression = sc.nextLine();String result = evaluate(expression);System.out.println(result);}private static String evaluate(String expression) {try {// 清除表达式中的空格expression = expression.replaceAll(" ", "");// 计算表达式结果BigInteger[] result = eval(expression, 0, expression.length());// 处理并格式化结果输出if (result[1].equals(BigInteger.ZERO)) {return "ERROR"; // 遇到除数为零} else if (result[1].equals(BigInteger.ONE)) {return result[0].toString(); // 结果为整数} else {return result[0] + "/" + result[1]; // 输出最简分数}} catch (ArithmeticException e) {return "ERROR";}}// 解析并计算表达式private static BigInteger[] eval(String s, int start, int end) {// 分子和分母BigInteger numerator = BigInteger.ZERO;BigInteger denominator = BigInteger.ONE;BigInteger currentNumerator = BigInteger.ZERO;BigInteger currentDenominator = BigInteger.ONE;char lastOp = '+';for (int i = start; i < end; i++) {char ch = s.charAt(i);if (ch >= '0' && ch <= '9') {// 数字的处理int j = i;while (j < end && Character.isDigit(s.charAt(j))) j++;currentNumerator = new BigInteger(s.substring(i, j));currentDenominator = BigInteger.ONE;i = j - 1;} else if (ch == '(') {// 括号的处理int count = 1;int j = i + 1;while (j < end && count != 0) {if (s.charAt(j) == '(') count++;if (s.charAt(j) == ')') count--;j++;}BigInteger[] res = eval(s, i + 1, j - 1);currentNumerator = res[0];currentDenominator = res[1];i = j - 1;} else if (ch == '+' || ch == '-' || ch == '*' || ch == '/') {// 运算符的处理if (lastOp == '+') {numerator = numerator.multiply(currentDenominator).add(currentNumerator.multiply(denominator));denominator = denominator.multiply(currentDenominator);} else if (lastOp == '-') {numerator = numerator.multiply(currentDenominator).subtract(currentNumerator.multiply(denominator));denominator = denominator.multiply(currentDenominator);} else if (lastOp == '*') {numerator = numerator.multiply(currentNumerator);denominator = denominator.multiply(currentDenominator);} else if (lastOp == '/') {numerator = numerator.multiply(currentDenominator);denominator = denominator.multiply(currentNumerator);}// 约分BigInteger gcd = numerator.gcd(denominator);numerator = numerator.divide(gcd);denominator = denominator.divide(gcd);// 更新最后的操作符lastOp = ch;currentNumerator = BigInteger.ZERO;currentDenominator = BigInteger.ONE;}}// 处理最后的运算符if (lastOp == '+') {numerator = numerator.multiply(currentDenominator).add(currentNumerator.multiply(denominator));denominator = denominator.multiply(currentDenominator);} else if (lastOp == '-') {numerator = numerator.multiply(currentDenominator).subtract(currentNumerator.multiply(denominator));denominator = denominator.multiply(currentDenominator);} else if (lastOp == '*') {numerator = numerator.multiply(currentNumerator);denominator = denominator.multiply(currentDenominator);} else if (lastOp == '/') {numerator = numerator.multiply(currentDenominator);denominator = denominator.multiply(currentNumerator);}// 约分BigInteger gcd = numerator.gcd(denominator);numerator = numerator.divide(gcd);denominator = denominator.divide(gcd);// 确保分母总是正数if (denominator.compareTo(BigInteger.ZERO) < 0) {denominator = denominator.negate();numerator = numerator.negate();}return new BigInteger[] {numerator, denominator};}
}
六、效果展示
1、输入
1 * (3*4/(8-(7+0)))
2、输出
12
3、说明
🏆下一篇:华为OD机试 - 简易内存池 - 逻辑分析(Java 2024 C卷 200分)
🏆本文收录于,华为OD机试(JAVA)真题(A卷+B卷+C卷)
刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。