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

如何修改仅支持单数字的递归Java计算器以适配多数字输入?

Fixing Your Recursive Java Calculator to Support Multi-Digit Numbers

Hey there! Let's get your calculator handling multi-digit numbers like 12+34 or (100-25)*4—this is a straightforward adjustment to your existing recursive descent parser. Here's the breakdown of what's needed and the updated code:

The Root Problem

Your current factor() method only reads one single digit before returning. To support numbers with multiple digits, we need to keep reading consecutive digit characters and build the full numeric value instead of stopping at the first one.

The Fix: Update the factor() Method

Replace your existing factor() with this version, which loops through consecutive digits to construct multi-digit numbers:

private int factor() throws ParseError, IOException {
    if (lookAheadToken == '(') {
        consume(lookAheadToken);
        int result = expr();
        if (lookAheadToken == ')') {
            consume(lookAheadToken);
            return result;
        } else throw new ParseError();
    }
    if (lookAheadToken < '0' || lookAheadToken > '9') throw new ParseError();
    
    // Build multi-digit number here
    int result = 0;
    while (lookAheadToken >= '0' && lookAheadToken <= '9') {
        result = result * 10 + evalDigit(lookAheadToken);
        consume(lookAheadToken);
    }
    return result;
}

How This Works

  • We start with result = 0 for the number we're building.
  • For each digit we encounter:
    • Multiply the current result by 10 (shifting it left, e.g., 1 becomes 10 when we're about to add 2 to make 12).
    • Add the value of the new digit (using your existing evalDigit() method).
    • Consume the digit and check if the next token is also a digit—if yes, repeat the loop.
  • Once we hit a non-digit token (operator, parenthesis, newline, etc.), we return the full multi-digit number.

Full Updated Code

Here's the complete calculator class with multi-digit support added (note: I also added a simple ParseError class since it wasn't included in your original code):

import java.io.IOException;
import java.io.InputStream;

public class Calculator {
    private int lookAheadToken;
    private InputStream inputStream;

    public Calculator(InputStream inputStream) throws IOException, ParseError {
        this.inputStream = inputStream;
        lookAheadToken = inputStream.read();
    }

    private void consume(int symbol) throws IOException, ParseError {
        if (lookAheadToken != symbol) throw new ParseError();
        lookAheadToken = inputStream.read();
    }

    private int evalDigit(int digit) {
        return digit - '0';
    }

    private void goal() throws ParseError, IOException {
        int result = expr();
        if (lookAheadToken == '\n') {
            System.out.println("result = " + result);
        }
        consume(lookAheadToken);
        if (lookAheadToken == -1) return;
        goal();
    }

    private int expr() throws ParseError, IOException {
        int result = term();
        return rest_expr(result);
    }

    private int rest_expr(int factor) throws ParseError, IOException {
        if (lookAheadToken == '\n' || lookAheadToken == ')' || lookAheadToken == -1) return factor;
        if (lookAheadToken != '+' && lookAheadToken != '-') throw new ParseError();
        char operator = (char) lookAheadToken;
        consume(lookAheadToken);
        int result = term();
        if (operator == '+') {
            return rest_expr(factor + result);
        } else if (operator == '-') {
            return rest_expr(factor - result);
        } else return factor;
    }

    private int term() throws ParseError, IOException {
        int result = factor();
        return rest_term(result);
    }

    private int rest_term(int factor) throws ParseError, IOException {
        if (lookAheadToken == '\n' || lookAheadToken == ')' || lookAheadToken == -1) return factor;
        if (lookAheadToken == '+' || lookAheadToken == '-') return factor;
        if (lookAheadToken != '*' && lookAheadToken != '/') throw new ParseError();
        char operator = (char) lookAheadToken;
        consume(lookAheadToken);
        int result = factor();
        if (operator == '*') {
            return rest_term(factor * result);
        } else if (operator == '/') {
            return rest_term(factor / result);
        } return factor;
    }

    private int factor() throws ParseError, IOException {
        if (lookAheadToken == '(') {
            consume(lookAheadToken);
            int result = expr();
            if (lookAheadToken == ')') {
                consume(lookAheadToken);
                return result;
            } else throw new ParseError();
        }
        if (lookAheadToken < '0' || lookAheadToken > '9') throw new ParseError();
        
        // Updated to build multi-digit numbers
        int result = 0;
        while (lookAheadToken >= '0' && lookAheadToken <= '9') {
            result = result * 10 + evalDigit(lookAheadToken);
            consume(lookAheadToken);
        }
        return result;
    }

    public static void main(String[] args) throws IOException, ParseError {
        InputStream inputStream = System.in;
        Calculator calculator = new Calculator(inputStream);
        calculator.goal();
    }

    // Custom exception for parsing errors
    static class ParseError extends Exception {}
}

Testing It Out

Try inputs like:

  • 12+34 → Should output result = 46
  • (100-25)*4 → Should output result = 300
  • 789/3 → Should output result = 263

This change maintains all your existing recursive logic for operator precedence and parentheses—we just extended the number-parsing part to handle multiple digits.

内容的提问来源于stack exchange,提问作者vasilis_dim

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:06:53