You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Studio Java中缀转后缀计算器输入小数点崩溃问题

问题说明

大学课程作业开发计算器应用,采用中缀转后缀(infix to postfix)规则实现计算逻辑,现有代码未适配小数点.的解析处理:输入包含小数点的表达式(例如1.1+)时程序会直接崩溃。经排查,运算符处理分支未覆盖小数点的相关处理逻辑,需要对应修复方案,也可提供更优的实现思路。

运行日志截图

运行日志截图

现有实现代码

class Solution {
public double calculate(String s) {
    if (s == null || s.length() < 1) return Integer.MIN_VALUE;
    return evalSuffix(inToSuffix(s));
}

public int rank(Character op) {
    switch (op) {
        case '+': return 1;
        case '-': return 1;
        case '*': return 2;
        case '/': return 2;
        case '%': return 2;
        case '^': return 3; //可自行扩展更多运算符
        default: return 0; //'('的优先级
    }
}

public List<Object> inToSuffix(String s) {
    Stack<Character> opStack = new Stack<>();
    List<Object> suffix = new LinkedList<>();
    double num = 0;
    boolean numCached = false;
    char[] chars = s.toCharArray();
    for (char c : chars) {
        if (Character.isDigit(c)) {
            num = num * 10 + (c - '0');
            numCached = true;
        }
        else {
            if (numCached) {
                suffix.add(num);
                num = 0;
                numCached = false;
            }
            if (c == ' ' || c == '\t') continue;
            if (c == '(') opStack.push('(');
            else if (c == ')') {
                while (opStack.peek() != '(') suffix.add(opStack.pop()); //括号内运算符优先出栈
                opStack.pop();
            }
            else {
                while (!opStack.isEmpty() && rank(c) <= rank(opStack.peek())) suffix.add(opStack.pop());
                opStack.push(c);
            }
        }
    }
    if (numCached) suffix.add(num);
    while (!opStack.isEmpty()) suffix.add(opStack.pop());
    return suffix;
}

public double evalSuffix(List<Object> suffix) {
    Stack<Double> numStack = new Stack<>();
    double num1 = 0;
    double num2 = 0;
    for (Object o : suffix) {
        if (o instanceof Character) {
            char op = (Character)o;
            num2 = numStack.pop();
            num1 = numStack.pop();
            switch (op) {
                case '+': numStack.push(num1 + num2); break;
                case '-': numStack.push(num1 - num2); break;
                case '*': numStack.push(num1 * num2); break;
                case '/': numStack.push(num1 / num2); break;
                case '%': numStack.push(num1 % num2); break;
                case '^': numStack.push((double)Math.pow((double)num1, (double)num2)); break;
            }
        }
        else numStack.push((Double) o);
    }
    return numStack.pop();
 }
}
修复方案

崩溃的核心原因是现有数字解析逻辑仅支持整数,遇到.会直接走运算符分支,既无法识别小数,也没有对应处理逻辑导致栈操作异常。修复只需要调整inToSuffix方法的数字解析部分,新增小数处理逻辑即可:

  • 新增两个状态变量:
    • isDecimal:布尔值,标记当前是否正在解析小数部分
    • decimalScale:小数位权重,初始为0.1,每解析一位小数就除以10
  • 遍历到.字符时做合法性校验:必须处于数字解析过程中、且当前数字还没出现过小数点,否则属于非法表达式;校验通过后标记isDecimal = true,初始化decimalScale = 0.1
  • 解析数字字符时,判断当前是否处于小数模式:小数模式下累加值为num += (c - '0') * decimalScale,之后decimalScale /= 10;整数模式沿用原有进位逻辑
  • 每次数字入栈、重置解析状态时,同步重置isDecimal和decimalScale的状态

修复后核心代码片段

仅展示修改后的inToSuffix方法,其余方法无需调整:

public List<Object> inToSuffix(String s) {
    Stack<Character> opStack = new Stack<>();
    List<Object> suffix = new LinkedList<>();
    double num = 0;
    boolean numCached = false;
    // 新增小数解析状态
    boolean isDecimal = false;
    double decimalScale = 0.1;
    char[] chars = s.toCharArray();
    for (char c : chars) {
        if (Character.isDigit(c)) {
            if (isDecimal) {
                // 小数部分累加
                num += (c - '0') * decimalScale;
                decimalScale /= 10;
            } else {
                // 整数部分原有逻辑
                num = num * 10 + (c - '0');
            }
            numCached = true;
        } else if (c == '.') {
            // 处理小数点:校验合法性,标记小数解析状态
            if (!numCached || isDecimal) {
                throw new IllegalArgumentException("非法的小数点位置");
            }
            isDecimal = true;
            decimalScale = 0.1;
        } else {
            if (numCached) {
                suffix.add(num);
                // 重置所有数字解析状态
                num = 0;
                numCached = false;
                isDecimal = false;
                decimalScale = 0.1;
            }
            if (c == ' ' || c == '\t') continue;
            if (c == '(') opStack.push('(');
            else if (c == ')') {
                while (opStack.peek() != '(') suffix.add(opStack.pop());
                opStack.pop();
            } else {
                while (!opStack.isEmpty() && rank(c) <= rank(opStack.peek())) suffix.add(opStack.pop());
                opStack.push(c);
            }
        }
    }
    if (numCached) suffix.add(num);
    while (!opStack.isEmpty()) suffix.add(opStack.pop());
    return suffix;
}
额外优化建议
  • 可以在方法入口新增表达式合法性校验,比如连续运算符、括号不匹配、首尾为运算符等场景提前抛出明确异常,避免运行时栈操作崩溃
  • 做除法运算时新增除数为0的校验,返回明确错误提示
  • 如果需要支持负数(比如-1+2或者3*-2这类场景),可以额外补全负号作为一元运算符的处理逻辑

内容的提问来源于stack exchange,提问作者c.dipu0

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 02:33:08