我的前缀表达式计算器出现问题
我的前缀表达式计算器遇到错误。
当我尝试运行它时出现的错误是
Expression (+ (- 6) (* 2 3 4) (/ (+ 3) (- 2 3 1)))
Expression in thread "main" java.lang.NumberFormatException: For input string: "(+ (- 6) (* 2 3 4) (/ (+ 3) (* 1) (- 2 3 1)))"
at sun.misc.FloatingDecimal.readJavaFormatException: For input string "(+ (- 6) (* 2 3 4) (/ (+ 3) (* 1) (- 2 3 1)))"
at sun.misc.FloatingDecimal.readJavaFormatString(Unknown Source)
//code starts here
import java.util.*;
public class SimpleLispExpressionEvaluator {
// Current input Lisp expression
private String inputExpr;
// Main stack & temp stack, see algorithm in evaluate()
private Stack<Object> expressionStack;
private Stack<Double> tempStack;
// default constructor
// set inputExpr to ""
// create stack objects
public SimpleLispExpressionEvaluator()
{
inputExpr = "";
expressionStack = new Stack<Object>();
tempStack = new Stack<Double>();
}
// default constructor
// set inputExpr to inputExpression
// create stack objects
public SimpleLispExpressionEvaluator(String inputExpression)
{
inputExpr = inputExpression;
expressionStack = new Stack<Object>();
tempStack = new Stack<Double>();
}
// set inputExpr to inputExpression
// clear stack objects
public void reset(String inputExpression)
{
inputExpr = inputExpression;
Stack<Object> expressionStack = new Stack<Object>();
Stack<Double> tempstack = new Stack<Double>();
}
private boolean checkifNumber() {
return false;
}
// This function evaluate current operator with its operands
// See complete algorithm in evaluate()
//
// Main Steps:
// Pop operands from expressionStack and push them onto
// tempStack until you find an operator
// Apply the operator to the operands on tempStack
// Push the result into expressionStack
//
`private double add() {
double op1 = tempStack.pop();
double op2 = tempStack.pop();
double temp = op1 + op2;
return temp;
}`
private double multiply() {
double op1 = tempStack.pop();
double op2 = tempStack.pop();
double temp = op1 * op2;
return temp;
}
private double subtract() {
if (tempStack.size() == 1) {
double temp = -tempStack.pop();
return temp;
} else {
double op1 = tempStack.pop();
double op2 = tempStack.pop();
double temp = op1 - op2;
return temp;
}
}
private double divide() {
if (tempStack.size() == 1) {
double temp = 1 / tempStack.pop();
return temp;
} else if (tempStack.pop() == 0 || tempStack.pop() == null) {
throw new IndexOutOfBoundsException(); } else {
double op1 = tempStack.pop();
double op2 = tempStack.pop();
double temp = op1 - op2;
return temp;
}
}
private void evaluateCurrentOperation()
{
while( expressionStack.peek().getClass().getName().equals("java.lang.Double") ) {
tempStack.push( (Double)expressionStack.pop() );
}
Character operator = (Character)expressionStack.pop();
Double result = null;
switch( operator ) {
case '+':
result = add();
break;
case '*':
result = multiply();
break;
case '-':
result = subtract();
break;
case '/':
result = divide();
break;
}
expressionStack.push( result );
}
/**
* This function evaluates Lisp expression in inputExpr
* It return result of the expression
*
* The algorithm:
*
* Step 1 Scan the tokens in the expression string.
* Step 2 If you see an operand, push operand object onto the expressionStack
* Step 3 If you see "(", next token should be an operator
* Step 4 If you see an operator, push operator object onto the expressionStack
* Step 5 If you see ")" // steps in evaluateCurrentOperation() :
* Step 6 Pop operands and push them onto tempStack
* until you find an operator
* Step 7 Apply the operator to the operands on tempStack
* Step 8 Push the result into expressionStack
* Step 9 If you run out of tokens, the value on the top of expressionStack is
* is the result of the expression.
*/
public double evaluate()
{
// only outline is given...
// you need to add statements
// you may delete or modify any statements in this method
// use scanner to tokenize inputExpr
Scanner inputExprScanner = new Scanner(inputExpr);
// Use zero or more white space as delimiter,
// which breaks the string into single character tokens
inputExprScanner = inputExprScanner.useDelimiter("\\s*");
// Step 1: Scan the tokens in the string.
while (inputExprScanner.hasNext())
{
// Step 2: If you see an operand, push operand object onto the expressionStack
if (inputExprScanner.hasNextInt())
{
// This force scanner to grab all of the digits
// Otherwise, it will just get one char
String dataString = inputExprScanner.findInLine("\\d+");
expressionStack.push(new Double(dataString));
// more ...
}
else
{
// Get next token, only one char in string token
String aToken = inputExprScanner.next();
char item = aToken.charAt(0);
String nextToken;
char nextItem;
switch (item)
{
// Step 3: If you see "(", next token should be an operator
case '(':
nextToken = inputExprScanner.next();
nextItem = nextToken.charAt(0);
// Step 4: If you see an operator, push operator object onto the expressionStack
if (nextItem == '+') {
expressionStack.push(nextItem);
} else if (nextItem == '-') {
expressionStack.push(nextItem);
} else if (nextItem == '*') {
expressionStack.push(nextItem);
} else {
expressionStack.push(nextItem);
}
break;
// Step 5: If you see ")" // steps 6,7,8 in evaluateCurrentOperation()
case ')':
try {
evaluateCurrentOperation();
} catch (EmptyStackException e) {
break;
}
break;
default: // error
throw new RuntimeException(item + " is not a legal expression operator");
} // end switch
} // end else
} // end while
// Step 9: If you run out of tokens, the value on the top of expressionStack is
// is the result of the expression.
//
// return result
double result = new Double(inputExpr);
return result;
}
// This static method is used by main() only
private static void evaluateExprt(String s, SimpleLispExpressionEvaluator expr)
{
Double result;
System.out.println("Expression " + s);
expr.reset(s);
result = expr.evaluate();
System.out.printf("Result %.2f\n", result);
System.out.println("-----------------------------");
}
// simple tests
public static void main (String args[])
{
SimpleLispExpressionEvaluator expr= new SimpleLispExpressionEvaluator();
String test1 = "(+ (- 6) (* 2 3 4) (/ (+ 3) (* 1) (- 2 3 1)))";
String test2 = "(+ (- 632) (* 21 3 4) (/ (+ 32) (* 1) (- 21 3 1)))";
String test3 = "(+ (/ 2) (* 2) (/ (+ 1) (+ 1) (- 2 1 )))";
String test4 = "(+ (/2))";
String test5 = "(+ (/2 3 0))";
String test6 = "(+ (/ 2) (* 2) (/ (+ 1) (+ 3) (- 2 1 ))))";
evaluateExprt(test1, expr);
evaluateExprt(test2, expr);
evaluateExprt(test3, expr);
evaluateExprt(test4, expr);
evaluateExprt(test5, expr);
evaluateExprt(test6, expr);
} }
I'm running into an error with my prefix expression evaluator.
The error that I get when I try to run it is
Expression (+ (- 6) (* 2 3 4) (/ (+ 3) (- 2 3 1)))
Expression in thread "main" java.lang.NumberFormatException: For input string: "(+ (- 6) (* 2 3 4) (/ (+ 3) (* 1) (- 2 3 1)))"
at sun.misc.FloatingDecimal.readJavaFormatException: For input string "(+ (- 6) (* 2 3 4) (/ (+ 3) (* 1) (- 2 3 1)))"
at sun.misc.FloatingDecimal.readJavaFormatString(Unknown Source)
//code starts here
import java.util.*;
public class SimpleLispExpressionEvaluator {
// Current input Lisp expression
private String inputExpr;
// Main stack & temp stack, see algorithm in evaluate()
private Stack<Object> expressionStack;
private Stack<Double> tempStack;
// default constructor
// set inputExpr to ""
// create stack objects
public SimpleLispExpressionEvaluator()
{
inputExpr = "";
expressionStack = new Stack<Object>();
tempStack = new Stack<Double>();
}
// default constructor
// set inputExpr to inputExpression
// create stack objects
public SimpleLispExpressionEvaluator(String inputExpression)
{
inputExpr = inputExpression;
expressionStack = new Stack<Object>();
tempStack = new Stack<Double>();
}
// set inputExpr to inputExpression
// clear stack objects
public void reset(String inputExpression)
{
inputExpr = inputExpression;
Stack<Object> expressionStack = new Stack<Object>();
Stack<Double> tempstack = new Stack<Double>();
}
private boolean checkifNumber() {
return false;
}
// This function evaluate current operator with its operands
// See complete algorithm in evaluate()
//
// Main Steps:
// Pop operands from expressionStack and push them onto
// tempStack until you find an operator
// Apply the operator to the operands on tempStack
// Push the result into expressionStack
//
`private double add() {
double op1 = tempStack.pop();
double op2 = tempStack.pop();
double temp = op1 + op2;
return temp;
}`
private double multiply() {
double op1 = tempStack.pop();
double op2 = tempStack.pop();
double temp = op1 * op2;
return temp;
}
private double subtract() {
if (tempStack.size() == 1) {
double temp = -tempStack.pop();
return temp;
} else {
double op1 = tempStack.pop();
double op2 = tempStack.pop();
double temp = op1 - op2;
return temp;
}
}
private double divide() {
if (tempStack.size() == 1) {
double temp = 1 / tempStack.pop();
return temp;
} else if (tempStack.pop() == 0 || tempStack.pop() == null) {
throw new IndexOutOfBoundsException(); } else {
double op1 = tempStack.pop();
double op2 = tempStack.pop();
double temp = op1 - op2;
return temp;
}
}
private void evaluateCurrentOperation()
{
while( expressionStack.peek().getClass().getName().equals("java.lang.Double") ) {
tempStack.push( (Double)expressionStack.pop() );
}
Character operator = (Character)expressionStack.pop();
Double result = null;
switch( operator ) {
case '+':
result = add();
break;
case '*':
result = multiply();
break;
case '-':
result = subtract();
break;
case '/':
result = divide();
break;
}
expressionStack.push( result );
}
/**
* This function evaluates Lisp expression in inputExpr
* It return result of the expression
*
* The algorithm:
*
* Step 1 Scan the tokens in the expression string.
* Step 2 If you see an operand, push operand object onto the expressionStack
* Step 3 If you see "(", next token should be an operator
* Step 4 If you see an operator, push operator object onto the expressionStack
* Step 5 If you see ")" // steps in evaluateCurrentOperation() :
* Step 6 Pop operands and push them onto tempStack
* until you find an operator
* Step 7 Apply the operator to the operands on tempStack
* Step 8 Push the result into expressionStack
* Step 9 If you run out of tokens, the value on the top of expressionStack is
* is the result of the expression.
*/
public double evaluate()
{
// only outline is given...
// you need to add statements
// you may delete or modify any statements in this method
// use scanner to tokenize inputExpr
Scanner inputExprScanner = new Scanner(inputExpr);
// Use zero or more white space as delimiter,
// which breaks the string into single character tokens
inputExprScanner = inputExprScanner.useDelimiter("\\s*");
// Step 1: Scan the tokens in the string.
while (inputExprScanner.hasNext())
{
// Step 2: If you see an operand, push operand object onto the expressionStack
if (inputExprScanner.hasNextInt())
{
// This force scanner to grab all of the digits
// Otherwise, it will just get one char
String dataString = inputExprScanner.findInLine("\\d+");
expressionStack.push(new Double(dataString));
// more ...
}
else
{
// Get next token, only one char in string token
String aToken = inputExprScanner.next();
char item = aToken.charAt(0);
String nextToken;
char nextItem;
switch (item)
{
// Step 3: If you see "(", next token should be an operator
case '(':
nextToken = inputExprScanner.next();
nextItem = nextToken.charAt(0);
// Step 4: If you see an operator, push operator object onto the expressionStack
if (nextItem == '+') {
expressionStack.push(nextItem);
} else if (nextItem == '-') {
expressionStack.push(nextItem);
} else if (nextItem == '*') {
expressionStack.push(nextItem);
} else {
expressionStack.push(nextItem);
}
break;
// Step 5: If you see ")" // steps 6,7,8 in evaluateCurrentOperation()
case ')':
try {
evaluateCurrentOperation();
} catch (EmptyStackException e) {
break;
}
break;
default: // error
throw new RuntimeException(item + " is not a legal expression operator");
} // end switch
} // end else
} // end while
// Step 9: If you run out of tokens, the value on the top of expressionStack is
// is the result of the expression.
//
// return result
double result = new Double(inputExpr);
return result;
}
// This static method is used by main() only
private static void evaluateExprt(String s, SimpleLispExpressionEvaluator expr)
{
Double result;
System.out.println("Expression " + s);
expr.reset(s);
result = expr.evaluate();
System.out.printf("Result %.2f\n", result);
System.out.println("-----------------------------");
}
// simple tests
public static void main (String args[])
{
SimpleLispExpressionEvaluator expr= new SimpleLispExpressionEvaluator();
String test1 = "(+ (- 6) (* 2 3 4) (/ (+ 3) (* 1) (- 2 3 1)))";
String test2 = "(+ (- 632) (* 21 3 4) (/ (+ 32) (* 1) (- 21 3 1)))";
String test3 = "(+ (/ 2) (* 2) (/ (+ 1) (+ 1) (- 2 1 )))";
String test4 = "(+ (/2))";
String test5 = "(+ (/2 3 0))";
String test6 = "(+ (/ 2) (* 2) (/ (+ 1) (+ 3) (- 2 1 ))))";
evaluateExprt(test1, expr);
evaluateExprt(test2, expr);
evaluateExprt(test3, expr);
evaluateExprt(test4, expr);
evaluateExprt(test5, expr);
evaluateExprt(test6, expr);
} }
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
evaluate
的第 9 步没有执行注释的操作:它尝试将整个输入字符串转换为双精度型,而不是检索表达式堆栈的顶部。应该
注意的是,实现时的运算符不接受 3 个或更多参数 -
(* 2 3 4)
不应该起作用。Step 9 of
evaluate
is not doing what is commented:it is trying to convert the whole input string into a double, not retrieving the top of the expression stack. It should be something like
also beware that the operators, as implemented, do not accept 3 or more arguments -
(* 2 3 4)
should not work.