forked from onlyliuxin/coding2017
-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request onlyliuxin#76 from miniyk2012/master
中缀表达式求值V1
- Loading branch information
Showing
4 changed files
with
194 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
134 changes: 134 additions & 0 deletions
134
.../812350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixExpr.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
package com.github.miniyk2012.coding2017.basic.stack.expr; | ||
|
||
import java.util.LinkedList; | ||
import java.util.List; | ||
import java.util.Stack; | ||
|
||
public class InfixExpr { | ||
private String expr = null; | ||
enum Operator { | ||
PLUS("+", 1), SUB("-", 1), MUL("*", 2), DIV("/", 2); // 优先级越大,说明应该先算 | ||
private String value; | ||
private int priority; | ||
Operator(String value, int prioriy) { | ||
this.value = value; | ||
this.priority = prioriy; | ||
} | ||
public static Operator parseOperator(String value) { | ||
for (Operator c : Operator.values()) { | ||
if (c.value.equals(value)) { | ||
return c; | ||
} | ||
} | ||
throw new RuntimeException("运算符不存在"); | ||
} | ||
} | ||
|
||
public InfixExpr(String expr) { | ||
this.expr = expr; | ||
} | ||
private static Token<Float> evaluate(Token<Operator> operator, Token<Float> number1, Token<Float> number2) { | ||
float ret; | ||
switch (operator.value) { | ||
case PLUS: | ||
ret = number1.getValue() + number2.getValue(); | ||
break; | ||
case SUB: | ||
ret = number1.getValue() - number2.getValue(); | ||
break; | ||
case MUL: | ||
ret = number1.getValue() * number2.getValue(); | ||
break; | ||
case DIV: | ||
ret = number1.getValue() / number2.getValue(); | ||
break; | ||
default: | ||
throw new RuntimeException("运算符不存在"); | ||
} | ||
return new Token(ret, true); | ||
} | ||
|
||
|
||
public float evaluate() { | ||
List<Token> tokens= Token.parse(expr); | ||
Stack<Token<Float>> numberStack = new Stack<>(); | ||
Stack<Token<Operator>> operatorStack = new Stack<>(); | ||
for (Token t : tokens) { | ||
if (t.isNumber()) { | ||
numberStack.push(t); | ||
} else { | ||
if (operatorStack.isEmpty()) { | ||
operatorStack.push(t); | ||
} else { | ||
Token<Operator> preT = operatorStack.peek(); | ||
if ((preT.value).priority >= ((Operator)t.value).priority) { | ||
Token number2 = numberStack.pop(); | ||
Token number1 = numberStack.pop(); | ||
operatorStack.pop(); | ||
numberStack.push(evaluate(preT, number1, number2)); | ||
} | ||
operatorStack.push(t); | ||
|
||
} | ||
} | ||
} | ||
while (!operatorStack.isEmpty()) { | ||
Token number2 = numberStack.pop(); | ||
Token number1 = numberStack.pop(); | ||
Token operator = operatorStack.pop(); | ||
numberStack.push(evaluate(operator, number1, number2)); | ||
} | ||
return numberStack.pop().getValue(); | ||
} | ||
|
||
|
||
private static class Token<T> { | ||
private boolean number; // 是数字/操作符 | ||
private T value; | ||
public boolean isNumber() { | ||
return number; | ||
} | ||
public T getValue() { | ||
return value; | ||
} | ||
|
||
public Token(T value, boolean number) { | ||
this.value = value; | ||
this.number = number; | ||
} | ||
public static List<Token> parse(String expr) { | ||
int i = 0; | ||
int size = expr.length(); | ||
String current; | ||
List<Token> tokens = new LinkedList<>(); | ||
String value = ""; | ||
while (i < size) { | ||
current = expr.substring(i,i+1); | ||
if (isOperator(current)) { | ||
tokens.add(new Token(Float.parseFloat(value), true)); | ||
value = ""; | ||
tokens.add(new Token(Operator.parseOperator(current), false)); | ||
} else { | ||
value += current; | ||
} | ||
i++; | ||
} | ||
tokens.add(new Token(Float.parseFloat(value), true)); | ||
return tokens; | ||
} | ||
|
||
private static boolean isOperator(String value) { | ||
for (Operator c : Operator.values()) { | ||
if (c.value.equals(value)) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
} | ||
|
||
public static void main(String[] args) { | ||
|
||
|
||
} | ||
} |
52 changes: 52 additions & 0 deletions
52
...350401/src/main/java/com/github/miniyk2012/coding2017/basic/stack/expr/InfixExprTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package com.github.miniyk2012.coding2017.basic.stack.expr; | ||
|
||
import org.junit.After; | ||
import org.junit.Assert; | ||
import org.junit.Before; | ||
import org.junit.Test; | ||
|
||
|
||
public class InfixExprTest { | ||
|
||
@Before | ||
public void setUp() throws Exception { | ||
} | ||
|
||
@After | ||
public void tearDown() throws Exception { | ||
} | ||
|
||
@Test | ||
public void testEvaluate() { | ||
//InfixExpr expr = new InfixExpr("300*20+12*5-20/4"); | ||
{ | ||
InfixExpr expr = new InfixExpr("2+3"); | ||
Assert.assertEquals(5.0, expr.evaluate(), 0.001f); | ||
} | ||
{ | ||
InfixExpr expr = new InfixExpr("2+3*4+5"); | ||
Assert.assertEquals(19.0, expr.evaluate(), 0.001f); | ||
} | ||
{ | ||
InfixExpr expr = new InfixExpr("3*20+12*5-40/2"); | ||
Assert.assertEquals(100.0, expr.evaluate(), 0.001f); | ||
} | ||
|
||
{ | ||
InfixExpr expr = new InfixExpr("3*20/2"); | ||
Assert.assertEquals(30, expr.evaluate(), 0.001f); | ||
} | ||
|
||
{ | ||
InfixExpr expr = new InfixExpr("20/2*3"); | ||
Assert.assertEquals(30, expr.evaluate(), 0.001f); | ||
} | ||
|
||
{ | ||
InfixExpr expr = new InfixExpr("10-30+50"); | ||
Assert.assertEquals(30, expr.evaluate(), 0.001f); | ||
} | ||
|
||
} | ||
|
||
} |