java四则运算器算法_java写的四则运算器
本打算做一個從RE到NFA的轉(zhuǎn)換器,思路已經(jīng)理清了,但是在動手做的時候,遇到了很多問題,有些技術(shù)難點都遺忘了,包括如何定義閉包,如何利用遞歸來實現(xiàn)。?于是回頭重新拾起這些技術(shù),邊學(xué)邊思考,做了個四則運算器練練手,為著那個大目標(biāo)做準(zhǔn)備。
基本的思路是這樣的:?根據(jù)輸入的四則運算表達(dá)式,生成一棵二叉樹,樹的根節(jié)點是操作符,而子樹可能是葉子節(jié)點,即數(shù)字。也可能是另一個運算表達(dá)式。生成樹的規(guī)則是,對每一個節(jié)點產(chǎn)生一個相應(yīng)的type值,type值越大,就在樹的越靠上節(jié)點。基本原則是: 數(shù)字(10) < 乘除運算(20) < 加減運算(30)。?括號被當(dāng)做是一種特殊的符號,并不會在二叉樹上顯示出來,相應(yīng)的,它會影響到在括號內(nèi)出現(xiàn)符號的type值,每嵌套一層括號,就會將type值減少100, 這樣確保了括號內(nèi)的內(nèi)容在樹的最底層。?當(dāng)二叉樹構(gòu)造好了之后,利用遞歸,將左樹的計算結(jié)果與右樹的結(jié)果,根據(jù)根操作符計算出結(jié)果。?舉例:10?生成樹只有一個節(jié)點,同時也是根節(jié)點,返回值便是根節(jié)點值。?舉例: 10 + 2首先生成根節(jié)點為10,但當(dāng)讀入+時,+的type值比10高,因此上移,并成為新的跟節(jié)點,最后加入2,因為2比+type值小,因此作為右子節(jié)點。?舉例: 10 + 2 * 5當(dāng)讀入*時,*的type值比2大,因此上移,同時又比+的type值小,因此就在+與2之間插入新的節(jié)點。?舉例: 10 + 2 *(2 + 3)當(dāng)讀入(時,后面所產(chǎn)生的所有Node的type值會相應(yīng)的-100, 因此括號內(nèi)的+的type值就會比外面的*小,但是仍然比括號內(nèi)的數(shù)字大,這樣保證了在樹中,2+3會先執(zhí)行。當(dāng)讀入)時,offset清零。
public class Main { public static void main(String[] args) {
String exp = "(10 + 15) * 3 - 20 * 6 /5 - (8 + 14(2- 1))2 + 11(12 - 11)5";
//String exp = "12";
Main main = new Main();
Main.index = 0;
char[] input = main.prepare(exp.toCharArray());
System.out.println(main.cal(input)); }
/**
* Actual calculate method.
* @param exp
* @return
*/ public int cal(char[] exp) {
Node root = buildTree(exp);
return calculate(root); }
/**
* Prepare the exp, remove empty space or \n.
* Also the method will add losing * in below cases:
* 10(3-1)
---->
10*(3-1)
* (3-1)10
---->
(3-1)*10
*
* @param exp
* @return
*/ public char[] prepare(char[] exp) {
char[] worklist = new char[exp.length];
int j = 0;
for (int i = 0; i < exp.length; i++) {
char c = exp[i];
if (c == ' ' || c == '\n') {
continue;
} else {
if (c == '(') { // Handle the abbreviated * for (
if(j == 0 || isCalculator(worklist[j - 1])) {
//Do nothing.
} else {
worklist[j++] = '*';
}
worklist[j++] = c;
} else if (c == ')') {// Handle the abbreviated * for )
worklist[j++] = c;
while((i == exp.length - 1) || (exp[++i] == ' ')) {
//Do nothing.
}
if(isCalculator(exp[i]) || exp[i] == ')') {
//Do nothing.
} else {
worklist[j++] = '*';
}
i--;
} else {
worklist[j++] = c;
}
}
}
char[] result = new char[j];
System.arraycopy(worklist, 0, result, 0, j);
return result; }
/**
* Check if c is a calculator or not.
* @param c
* @return
*/ private boolean isCalculator(char c) {
if(c == '+' || c == '-' || c == '*' || c == '/') {
return true;
}
return false; }
/**
* Calculate the tree.
*
* @param node
* @return
*/ private int calculate(Node node) {
if(node.isLeaf()) return Integer.parseInt(node.value);
if(node.value.equals("+")) {
return calculate(node.leftChild) + calculate(node.rightChild);
} else if(node.value.equals("-")) {
return calculate(node.leftChild) - calculate(node.rightChild);
} else if(node.value.equals("*")) {
return calculate(node.leftChild) * calculate(node.rightChild);
}else {
return calculate(node.leftChild) / calculate(node.rightChild);
} }
/**
* Build a tree like this:
*
* 10 * (3 + 5)
*
* ------ 10
*
-
*
------ +
*
-
*
------- 3
*
------- 5
* @param exp
* @return
*/ private Node buildTree(char[] exp) {
Node root = null;
Node working = null;
while(true) {
Node node = readNext(exp);
if(node == null) break;
if(root == null) {
root = node;
working = node;
continue;
}
if(node.type > working.type) {
Node parent = working.parent;
boolean isLeft = false;
while(parent != null && node.type >= parent.type) {
isLeft = parent.isLeft;
working = parent;
parent = parent.parent;
}
if(parent == null) {
working.parent = node;
node.leftChild = working;
working.isLeft = true;
root = node;
} else {
Node tmp = isLeft ? parent.leftChild : parent.rightChild;
if(isLeft) {
parent.leftChild = node;
} else {
parent.rightChild = node;
}
node.isLeft = isLeft;
node.parent = parent;
tmp.parent = node;
node.leftChild = tmp;
tmp.isLeft = true;
}
} else {
working.rightChild = node;
node.isLeft = false;
node.parent = working;
}
working = node;
}
return root; }
private static int index = 0; // Read the next node, it possible to be a number, a calculator or just space. private Node readNext(char[] exp) {
if(index >= exp.length) return null;
Node node = new Node();
char c = exp[index++];
if(Character.isDigit(c)) {
node.type = Node.NUMBER + offset;
StringBuffer sb = new StringBuffer();
sb.append(c);
for(; index < exp.length; index++) {
char tmp = exp[index];
if(Character.isDigit(tmp)) {
sb.append(tmp);
} else {
break;
}
}
node.value = sb.toString();
} else if (c == '*' || c == '/') {
node.type = Node.MUL_DEL + offset;
node.value = Character.toString(c);
}else if (c == '+' || c == '-') {
node.type = Node.PLUS_MINUS + offset;
node.value = Character.toString(c);
} else if(c == '(') {
increaseOffset();
return readNext(exp);
}else if(c == ')') {
decreaseOffset();
return readNext(exp);
}
return node; }
// Every type in the embrace will have to add a offset as their type. private static int offset = 0; public static void increaseOffset() {
offset = offset - 100; }
public static void decreaseOffset() {
offset = offset + 100; }
/**
* Helping class.
*
*/ class Node {
private int type = 10;
private Node parent = null;
private Node leftChild = null;
private Node rightChild = null;
private boolean isLeft = false;
private String value = null;
public Node() {
}
public static final int NUMBER = 10;
public static final int MUL_DEL = 20;
public static final int PLUS_MINUS = 30;
public static final int EMBRACE = -100;
public boolean isLeaf() {
if(leftChild == null && rightChild == null) {
return true;
}
return false;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public Node getParent() {
return parent;
}
public void setParent(Node parent) {
this.parent = parent;
}
public Node getLeftChild() {
return leftChild;
}
public void setLeftChild(Node leftChild) {
this.leftChild = leftChild;
}
public Node getRightChild() {
return rightChild;
}
public void setRightChild(Node rightChild) {
this.rightChild = rightChild;
}
public boolean isLeft() {
return isLeft;
}
public void setLeft(boolean isLeft) {
this.isLeft = isLeft;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
} }}
總結(jié)
以上是生活随笔為你收集整理的java四则运算器算法_java写的四则运算器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux mysql 5.6.24_M
- 下一篇: java监控网卡_VC++监控网卡状态