- 浏览: 253340 次
- 性别:
- 来自: 南京
文章分类
最新评论
-
mabusyao:
漠北空城 写道请问下,你这个是JDK版本是多少呢?!忘记了,应 ...
HashMap 源码解读 -
漠北空城:
请问下,你这个是JDK版本是多少呢?!
HashMap 源码解读 -
schumee:
完美团队~
项目沉思录 - 1.1 -
winie:
整理下 搞成引擎嘛 国产需要这样的engine
简单工作流引擎 -
mabusyao:
某位同学给我提供的堪称完美的解决方案:1. 将三个int数组放 ...
CraneWork
本打算做一个从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; } } }
发表评论
-
大数据下的实体解析
2016-07-07 12:03 671大数据时代的实体解析困境 <!--[if !sup ... -
中文相似度匹配算法
2015-12-30 14:44 1921基于音形码的中文字 ... -
各种语言写的wordcount
2015-09-24 16:07 0Java版本: String input ... -
数组双指针算法的研究
2015-07-14 16:59 2461双指针算法在数组/链 ... -
初识ThreadLocal
2015-07-07 13:15 1516最近公司在进行Java开发人员的招聘活动,其中有一道面试题 ... -
摩尔投票法
2015-06-30 20:13 18413摩尔投票法 提问: 给定一个int型数组,找出该数 ... -
(转)最长回文字串算法
2015-01-18 14:30 1438来自(http://blog.163.com/zhaohai ... -
小心寄存器
2012-11-08 13:53 4试试这段代码就知道了 public cla ... -
简单工作流引擎
2012-07-06 16:58 2414从公司的一个项目中挖出来的工作流引擎的代码,虽然是一个很简单的 ... -
Always clean the ThreadLocal variables.
2012-05-24 09:16 1217Any variable stored in ThreadLo ... -
STRUTS2 源码 - Logging System
2012-05-24 08:51 1405看了STRUTS2的源码,了解了它的logging系统,觉得还 ... -
在线词典的数据结构实现。
2012-05-18 08:37 0昨天在网上看到了一道百度的面试题: Baidu写道 ... -
Log4j 代码学习 - Factory
2012-05-17 08:47 1110我们最早提到,Log4j的初始代码在LogManager的静态 ... -
Log4j 代码学习 - Appender
2012-05-16 09:09 1357在上一篇文章里,我们 ... -
Log4j 代码学习
2012-05-15 14:58 1163最近闲来无事,正好手头上有Log4j的代码,于是就拿来学习了下 ... -
存储中间计算结果的动态规划算法
2012-04-18 15:50 1218public class RodCutting { ... -
java7中的ThreadLocalRandom(转)
2012-01-20 09:08 4348今天早上看到一个关于java7中的ThreadLocalRan ... -
(转)追MM与23种设计模式
2011-11-16 14:13 10001、FACTORY—追MM少不了请吃饭了,麦当劳的鸡翅和肯德 ... -
(转)Java 参数列表
2011-11-05 19:48 2926下面的讨论以Windows ... -
(转)TOMCAT源码分析
2011-10-17 16:06 2137TOMCAT源码分析(启动框架 ...
相关推荐
在Java编程语言中,四则运算器是一种程序,它能够执行基本的数学操作,包括加法(+)、减法(-)、乘法(*)和除法(/)。这类程序通常用于教学目的,以帮助初学者理解如何在Java中处理数字和运算。在这个“java.四...
本项目是一个基于Java的四则运算器,适用于初学者理解和实践Java的基础语法和控制流程。四则运算器是计算机科学中最基本的计算工具,能够进行加法、减法、乘法和除法操作。 首先,`Calc.java` 文件是这个项目的源...
用java开发四则运算器,解压后只接运行即可。 带有原码和注释。图形界面。
该程序是基于GUI设计的一款小型四则运算器,java爱好者参考参考!!
通过以上步骤,我们可以构建一个功能完备的四则运算题目生成器,它不仅能满足基本的运算题生成,还能根据需求进行扩展,提升用户体验。对于学习Java编程和理解面向对象设计原则的学生来说,这是一个很好的实践项目。
用JAVA简单实现了一个小学生运算器,包括加减乘除四种运算。
自动生成 10 道 100 以内的 2 个操作数的四则运算算式(+ - * /),要求运算结果也在 100 以内,把运算式存入“result.txt”文件中。题目数量、数字范围、操作数和运算规则是可控的。 使用-n 参数控制生成题目的个数...
### Java四则运算计算器知识点详解 #### 一、项目概述 **标题与描述解析:**“Java四则运算计算器”是一款基于Java语言开发的计算器应用,能够执行加、减、乘、除等基本算术运算,并支持混合运算,具备友好的用户...
使用图形用户界面编写一个小学生整数四则运算练习软件。程序启动后,用户输入用户名,然后选择做什么运算(加、减、乘、除、混合)、做几位数的运算,再单击“开始做题”,之后计算机按要求随机生成10道题目,用户...
是用JAVA编写的小型计算器,有基本的加,减,乘,除,功能。程序结构比较简单,适合用于初学者。
在本Java项目中,"operation 简易四则运算器"是一个基于简单工厂设计模式实现的计算工具,旨在帮助用户进行基本的加减乘除运算。该项目充分体现了面向对象编程的思想,通过封装、继承和多态性来提高代码的可读性和可...
java代码-使用java创建随机加法运算器的源代码 ——学习参考资料:仅用于个人学习使用!
在Java编程语言中,复数运算器是一种程序,它允许用户执行涉及复数的数学运算。复数是数学中的一个概念,表示为a + bi的形式,其中a是实部,b是虚部,i是虚数单位,满足i² = -1。这个“java复数运算器”项目提供了...
基于java的简单运算器程序 欢迎下载
### 四则运算JAVA计算器知识点解析 #### 一、项目概述 该项目是一个基于Java Swing的简单计算器应用程序,能够实现基本的四则运算功能,并且支持括号操作,以解决优先级问题。为了处理复杂的数学表达式,该计算器还...
在这个Java二进制运算器中,我们将深入探讨这些基本操作以及如何在代码中实现它们。 1. **二进制数系统**: 二进制是计算机科学中的基础,只有两个数字0和1。所有的计算都在这个系统下进行,因为计算机内部处理的是...
四则运算解析器是一种计算机程序,它能够接收包含加、减、乘、除等四则运算符的字符串表达式,并将其转化为可执行的计算过程。这个解析器通常用于解决基础的数学问题,对于编程初学者来说,理解并实现这样一个解析器...
【基于C#的四则运算器】是一种编程实践项目,主要使用C#语言来实现一个基本的计算器程序,能够执行加、减、乘、除四种基本的数学运算。这个项目对于初学者来说是一个很好的起点,它能帮助理解C#编程的基础语法、控制...
import java.io.*; public class Book{ double sb; double xb; Book(double x,double y){ this.sb=x; this.xb=y; } Book(){ } public static void main(String args[]){ System.out.println("请...