java - Java 递归前缀解析器阶乘

标签 java recursion factorial

我最近开始在大学学习java,我们要做的任务是理解递归并向这个波兰表示法代码添加阶乘函数。我尝试过各种方法,这是最新的:

public class PolishNotation {

    public static void main(String[] args) {
        try (Scanner scanner = new Scanner(System.in)) {
            System.out.println("Please enter the operators");
            System.out.println("for operators +, -, *, and !");
            System.out.println("Leave spaces between all operators and digits");
            System.out.print("expression: ");
            System.out.println("value = " + evaluateEXP(scanner));
        }
    }

    //input contains the expression user has entered
    public static int evaluateEXP(Scanner scanner) {
        //checks if there is another digit after current one
        //allows expression to be looked at from right to left
        if (scanner.hasNextInt())
            return scanner.nextInt();

        //if there is another digit after current one then
        //operands and operators are established
        char operator = scanner.next().charAt(0);
        int operand1 = evaluateEXP(scanner);
        int operand2 = evaluateEXP(scanner);
        return evaluateOP(operator, operand1, operand2);
    }

    //operator has to be one of +, - , * or ! otherwise error is given
    private static int evaluateOP(char operator, int operand1, int operand2) {
        if (operator == '+')
            return operand1 + operand2;
        if (operator == '-')
            return operand1 - operand2;
        if (operator == '*')
            return operand1 * operand2;
        if (operator == '/')
            return operand1 / operand2;
        if (operator == '!')
            //if ! used then uses factorial method
            return factorial(operand1);
        //RunTimeException allows to return an error string in a int "type" method
        throw new RuntimeException("operator not allowed for this language");
    }

    private static int factorial(int n) {
        return n == 1 ? 1 : factorial(n - 1) * n;
    }

}

没有错误,但结果没有出来,所以我猜测它陷入了无限循环。这段代码的想法是,如果我这样做了! + 3 2 它应该做 !5 所以返回 120 并且我不能使用 while 或 for 循环。其余操作数都有效,只是阶乘不起作用。

最佳答案

问题在于,在 evaluateEXP 中,您的代码始终需要 2 个操作数。然而 ! 仅接受一个操作数,因此如果您输入类似 ! 5它将等待更多输入。

解决方案是检查运算符是一元还是二元,如果是一元则只接受一个操作数。以下是重构代码以实现此目的的几种方法:

1) 检查 evaluateEXP 方法中的运算符,仅获取第二个操作数(如果它是二进制的)(在您的情况下不是 !):

//input contains the expression user has entered
public static int evaluateEXP(Scanner scanner) {
    //checks if there is another digit after current one
    //allows expression to be looked at from right to left
    if (scanner.hasNextInt())
        return scanner.nextInt();

    //if there is another digit after current one then
    //operands and operators are established
    char operator = scanner.next().charAt(0);
    int operand1 = evaluateEXP(scanner);
    int operand2 = 0;
    //only take second operand if operator is not unary
    if (operator != '!') {
        operand2 = evaluateEXP(scanner);
    }
    return evaluateOP(operator, operand1, operand2);
}

2)将扫描器传递给evaluateOP并让它直接获取操作数:

//input contains the expression user has entered
public static int evaluateEXP(Scanner scanner) {
    //checks if there is another digit after current one
    //allows expression to be looked at from right to left
    if (scanner.hasNextInt())
        return scanner.nextInt();

    //if there is another digit after current one then
    //operands and operators are established
    char operator = scanner.next().charAt(0);
    return evaluateOP(operator, scanner);
}

//operator has to be one of +, - , * or ! otherwise error is given
private static int evaluateOP(char operator, Scanner scanner) {
    if (operator == '+')
        return evaluateEXP(scanner) + evaluateEXP(scanner);
    if (operator == '-')
        return evaluateEXP(scanner) - evaluateEXP(scanner);
    if (operator == '*')
        return evaluateEXP(scanner) * evaluateEXP(scanner);
    if (operator == '/')
        return evaluateEXP(scanner) / evaluateEXP(scanner);
    if (operator == '!')
        //if ! used then uses factorial method
        return factorial(evaluateEXP(scanner));
    //RunTimeException allows to return an error string in a int "type" method
    throw new RuntimeException("operator not allowed for this language");
}

3)在第二个解决方案的基础上,您还可以合并这两种方法,因为它们无论如何都紧密相连:

//input contains the expression user has entered
public static int evaluateEXP(Scanner scanner) {
    //checks if there is another digit after current one
    //allows expression to be looked at from right to left
    if (scanner.hasNextInt())
        return scanner.nextInt();

    //if there is another digit after current one then
    //operands and operators are established
    char operator = scanner.next().charAt(0);

    if (operator == '+')
        return evaluateEXP(scanner) + evaluateEXP(scanner);
    if (operator == '-')
        return evaluateEXP(scanner) - evaluateEXP(scanner);
    if (operator == '*')
        return evaluateEXP(scanner) * evaluateEXP(scanner);
    if (operator == '/')
        return evaluateEXP(scanner) / evaluateEXP(scanner);
    if (operator == '!')
        //if ! used then uses factorial method
        return factorial(evaluateEXP(scanner));
    //RunTimeException allows to return an error string in a int "type" method
    throw new RuntimeException("operator not allowed for this language");
}

关于java - Java 递归前缀解析器阶乘,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52767633/

相关文章:

java - Android RAM页面大小?

java - 与赋值运算符相比,使用后修复运算符有哪些优点/限制?

c - C 语言谜题解决方案的问题 (CodeChef.com)

java - 紧密耦合的 fragment 在 Android 中可以吗(在某些情况下)?

java - Displaytag JSP 错误 - "Can not find tag library descriptor"

linux - 如何将 `chmod -R +w` 与 Ant、文件和文件夹一起使用?

recursion - Lisp 编程错误(堆栈溢出(深))

python - 在递归函数中复制 python 中的列表对象 - 奇怪的行为

c - 在 C.= 中计算阶乘时得到错误结果

function - 实现递归函数(阶乘)时出现堆栈溢出错误