java四则运算器算法_java写的四则运算器
本打算做一个从RE到NFA的转换器,思路已经理清了,但是在动手做的时候,遇到了很多问题,有些技术难点都遗忘了,包括如何定义闭包,如何利用递归来实现。 于是回头重新拾起这些技术,边学边思考,做了个四则运算器练练手,为着那个大目标做准备。
基本的思路是这样的: 根据输入的四则运算表达式,生成一棵二叉树,树的根节点是操作符,而子树可能是叶子节点,即数字。也可能是另一个运算表达式。生成树的规则是,对每一个节点产生一个相应的type值,type值越大,就在树的越靠上节点。基本原则是: 数字(10) < 乘除运算(20) < 加减运算(30)。 括号被当做是一种特殊的符号,并不会在二叉树上显示出来,相应的,它会影响到在括号内出现符号的type值,每嵌套一层括号,就会将type值减少100, 这样确保了括号内的内容在树的最底层。 当二叉树构造好了之后,利用递归,将左树的计算结果与右树的结果,根据根操作符计算出结果。 举例:10 生成树只有一个节点,同时也是根节点,返回值便是根节点值。 举例: 10 + 2首先生成根节点为10,但当读入+时,+的type值比10高,因此上移,并成为新的跟节点,最后加入2,因为2比+type值小,因此作为右子节点。 举例: 10 + 2 * 5当读入*时,*的type值比2大,因此上移,同时又比+的type值小,因此就在+与2之间插入新的节点。 举例: 10 + 2 *(2 + 3)当读入(时,后面所产生的所有Node的type值会相应的-100, 因此括号内的+的type值就会比外面的*小,但是仍然比括号内的数字大,这样保证了在树中,2+3会先执行。当读入)时,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;
} }}
java四则运算器算法_java写的四则运算器相关推荐
- java密码学原型算法_java密码学原型算法实现——双线性对.pdf
java密码学原型算法实现--双线性对 Java 密码学原型算法实现--双线性对 1.背景介绍 如何使用jPBC 库进行双线性群初始化,包括: (1)质数阶双线性群(Prime-Order Bilin ...
- java 求交集 算法_Java计算交集,差集,并集的方法示例
Java计算交集,差集,并集的方法示例 发布时间:2020-10-07 10:37:46 来源:脚本之家 阅读:106 作者:benbenkui 本文实例讲述了Java计算交集,差集,并集的方法.分享 ...
- java 数独算法_JAVA写的数独,附带生成唯一解和各种难度的算法
[实例简介] 自己用GUI写的一个数独小游戏..可选择难度,生成一个只有唯一解的数独..可显示答案,玩家也可以自己做题.代码+算法全在里面 [实例截图] [核心代码] Sudoku ├── Sudok ...
- java实现简单四则运算_JAVA实现简单四则混合运算
java实现加减乘除混合运算, http://www.oschina.net/code/snippet_189899_36597 这个算法很好, 加法 加号前面的加上加号后面的 减法 减号前面的减去减 ...
- java gc回收算法_Java GC回收算法-判定一个对象是否可以回收
开源推荐 推荐一款一站式性能监控工具(开源项目) Pepper-Metrics是跟一位同事一起开发的开源组件,主要功能是通过比较轻量的方式与常用开源组件(jedis/mybatis/motan/dub ...
- java 年轻代算法_java内存模型 年轻代/年老代 持久区,jvm中的年轻代 老年代 持久代 gc...
虚拟机中的共划分为三个代:年轻代(Young Generation).老年代(Old Generation)和持久代(Permanent Generation).其中持久代主要存放的是Java类的类信 ...
- java实现随机数生成算法_Java 语言实现的随机数生成算法
广州疯狂软件学院拥有三大课程体系包括:java课程,android课程,ios课程,疯狂软件年终钜惠,报名java就业班,免费赠送基础班,名额有限,本月火热报名中,欢迎有志之士电话或者QQ咨询. [导 ...
- java快速查找算法_Java实现的快速查找算法示例
本文实例讲述了Java实现的快速查找算法.分享给大家供大家参考,具体如下: 快速查找算法,可以根据想要找的是第几个大的数,每次循环都能固定下来一个数在数组完整排完序之后的位置,每次循环都能定一个数的位 ...
- java编写一个通讯录_java写的通讯录(小玩意)
上次有发个超级菜鸟级别的连接access的小程序 受兄弟委托,如今表妹期末了,要写个通讯录 于是草草的给写了个,毕竟有一个学期了,所以这次的代码会比较合理些-- 使用说明: 实现技术:java语言,界 ...
最新文章
- 开发顺序工作流时注意的几个事项
- FJWC 2019 游记
- php万年历上个月下个月,php 万年历
- mysql 查询语句_SQL语言mysql基础查询语句
- Java GregorianCalendar computeFields()方法与示例
- NginxJava笔记-Webservice使用HTTPS协议及Spring Boot配置tomcat
- html页面底部白条,用cookie解决新版微信中H5页面底部白条问题
- java thread join()_Java中Thread.join()的使用方法
- HTTP与Tcp协议下双工通信的差异
- 计算机信息管理试卷答案,计算机信息管理专业《计算机组成原理》试卷B和参考答案4...
- jQuery中的css部分
- 安装Linux系统的一些问题记载
- python函数速查手册_Pandas常用函数速查手册中文版
- python http请求时gzip解压
- 亲民地理第39期-佛山(2)南风古灶
- 看完必会的正则表达式和递归
- mysql自定义函数的创建
- 花生棒虚拟服务器,花生棒 开服务器
- PQI Air Card:自带Wi-fi的闪存卡 即时分享精彩画面
- minigui源码学习