我最近开始在uni中学习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循环。其余的操作数起作用了,只有阶乘不起作用。
发布于 2018-10-12 05:04:06
问题是在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");
}
发布于 2018-10-12 03:38:37
public static int factorial(int n) {
if(n==1){
return 1;
}
// the next line is wrong. I've removed a set of parentheses to make it more clear
int output = factorial((n-1)*n);
return output;
}
我强烈建议在你的脑海中运行你的代码。如果我将2传递给你的方法,用递归方式调用factorial()的值是什么?提示:它不是1。
发布于 2018-10-12 03:56:41
public static long fact(int n) {
return n == 0 ? 1L : n * fact(n - 1);
}
由于17!
大于Integer.MAX_VALUE
,因此最好使用long
作为返回类型
https://stackoverflow.com/questions/52767633
复制相似问题