`

Java实现四则混合运算

    博客分类:
  • Java
阅读更多

使用栈来实现,可以处理运算优先级。

使用自然四则运算表达式即可,如:4+(3*(3-1)+2)/2。无需把表达式先转换为逆波兰等形式。

 

package com.joshua.cal;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;

public class Calculator {

	private final Stack<Double> numStack = new Stack<Double>();
	private final Stack<Character> opStack = new Stack<Character>();

	private char currentOperator;
	private char opStackTop;

	private int i;
	private String expression;

	@SuppressWarnings("rawtypes")
	public void exec(String expression) {
		try {
			clean();
			if (expression == null || expression.isEmpty()) {
				throw new IllegalArgumentException("Blank Expression!");
			}
			this.expression = expression;
			opStack.push(TERMINATE_TOKENS.START_END_MARK);
			List tokens = TOKENIZER.exec(expression
					+ TERMINATE_TOKENS.START_END_MARK);
			for (; i < tokens.size(); i++) {
				final Object token = tokens.get(i);
				if (token instanceof Double) {
					processOperand((double) token);
				} else {
					processOperator((char) token);
				}
			}
		} catch (Throwable e) {
			System.err.println(String.format(
					"Incorret Expression: %s\nError: %s", expression,
					e.getMessage()));
		}
	}

	private void processOperand(final double operand) {
		numStack.push(operand);
	}

	private void processOperator(final char currentOperator) {
		this.currentOperator = currentOperator;
		this.opStackTop = opStack.peek();
		char calMode = CALCULATE_MODE.getRule(currentOperator, opStackTop);
		switch (calMode) {
		case '>':
			processStackHigerPriorityOperator();
			break;
		case '<':
			processStackLowerPriorityOperator();
			break;
		case '=':
			processStackEqualPriorityOperator();
			break;
		default:
			break;
		}
	}

	private void processStackLowerPriorityOperator() {
		opStack.push(currentOperator);
	}

	private void processStackHigerPriorityOperator() {
		numStack.push(CALCULATE.exec(opStack.pop(), numStack.pop(),
				numStack.pop()));
		--i; // pointer back to the previous operator.
	}

	private void processStackEqualPriorityOperator() {
		if (TERMINATE_TOKENS.START_END_MARK == currentOperator) {
			System.out.println(expression + " = " + numStack.peek());
		} else if (')' == currentOperator) {
			opStack.pop();
		}
	}

	public void clean() {
		numStack.clear();
		opStack.clear();
		i = 0;
	}

	public static void main(String[] args) {
		Calculator cal = new Calculator();
		cal.exec("4+(3*(3-1)+2)/2"); // = 8
		cal.exec("4 + (-3 * ( 3 - 1 ) + 2)"); // = 0
		cal.exec("4 +-/ (-3 * ( 3 - 1 ) + 2)"); // incorrect expression!
		cal.exec("4.5+(3.2+3)/2"); // = 7.6
		cal.exec("4.5+(3.2:3)/2"); // incorrect expression!
		cal.exec("-4.5+(3.2-3)/2"); // = -4.4
	}
}

enum CALCULATE {
	INSTANCE;

	public static double exec(final char operator, final double right,
			final double left) {
		switch (operator) {
		case '+':
			return left + right;
		case '-':
			return left - right;
		case '*':
			return left * right;
		case '/':
			return left / right;
		default:
			throw new IllegalArgumentException("Unsupported operator: "
					+ operator);
		}
	}
}

enum TERMINATE_TOKENS {
	INSTANCE;

	public static final char START_END_MARK = '#';
	private static final Map<Character, Integer> TOKENs = new HashMap<Character, Integer>();

	static {
		// token, token id
		TOKENs.put('+', 0);
		TOKENs.put('-', 1);
		TOKENs.put('*', 2);
		TOKENs.put('/', 3);
		TOKENs.put('(', 4);
		TOKENs.put(')', 5);
		TOKENs.put(START_END_MARK, 6);
	}

	private static Set<Character> NEGATIVE_NUM_SENSITIVE = new HashSet<Character>();

	public static synchronized Set<Character> getNegativeNumSensitiveToken() {
		if (NEGATIVE_NUM_SENSITIVE.size() == 0) {
			NEGATIVE_NUM_SENSITIVE.addAll(TOKENs.keySet());
			NEGATIVE_NUM_SENSITIVE.remove(')');
		}
		return NEGATIVE_NUM_SENSITIVE;
	}

	public static boolean isTerminateToken(final char token) {
		Set<Character> keys = TOKENs.keySet();
		return keys.contains(token);
	}

	public static int getTokenId(final char token) {
		return TOKENs.get(token) == null ? -1 : TOKENs.get(token);
	}

	public static int getTokenSize() {
		return TOKENs.size();
	}

}

enum CALCULATE_MODE {
	INSTANCE;

	private static char[][] RULES = {
			// + - * / ( ) #
			{ '>', '>', '<', '<', '<', '>', '>' }, // +
			{ '>', '>', '<', '<', '<', '>', '>' }, // -
			{ '>', '>', '>', '>', '<', '>', '>' }, // *
			{ '>', '>', '>', '>', '<', '>', '>' }, // /
			{ '<', '<', '<', '<', '<', '=', 'o' }, // (
			{ '>', '>', '>', '>', 'o', '>', '>' }, // )
			{ '<', '<', '<', '<', '<', 'o', '=' }, // #
	};

	static {
		if (RULES.length != TERMINATE_TOKENS.getTokenSize() || RULES.length < 1
				|| RULES[0].length != TERMINATE_TOKENS.getTokenSize()) {
			throw new IllegalArgumentException("Rules matrix is incorrect!");
		}
	}

	public static char getRule(final char currentOperator, final char opStackTop) {
		try {
			return RULES[TERMINATE_TOKENS.getTokenId(opStackTop)][TERMINATE_TOKENS
					.getTokenId(currentOperator)];
		} catch (Throwable e) {
			throw new RuntimeException("No rules were defined for some token!");
		}
	}
}

enum TOKENIZER {
	INSTANCE;

	private static final StringBuilder BUFFER = new StringBuilder();

	private static String clearExpression(String expression) {
		return expression.replaceAll(" ", "");
	}

	private static Character PREVIOUS_CHAR;

	private static void clean() {
		BUFFER.delete(0, BUFFER.length());
		PREVIOUS_CHAR = null;
	}

	private static boolean processNegativeNumbers(final String exp,
			final int index) {
		char c = exp.charAt(index);
		if (('+' == c || '-' == c)
				&& (PREVIOUS_CHAR == null || TERMINATE_TOKENS
						.getNegativeNumSensitiveToken().contains(PREVIOUS_CHAR))
				&& !TERMINATE_TOKENS.isTerminateToken(exp.charAt(index + 1))) {
			BUFFER.append(c);
			return true;
		}
		return false;
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static List<?> exec(final String expression) {
		clean();
		String exp = clearExpression(expression);
		List result = new LinkedList();
		for (int i = 0; i < exp.length(); i++) {
			char c = exp.charAt(i);
			if (TERMINATE_TOKENS.isTerminateToken(c)) {
				if (processNegativeNumbers(exp, i))
					continue;
				if (BUFFER.length() > 0) {
					result.add(Double.valueOf(BUFFER.toString()));
					BUFFER.delete(0, BUFFER.length());
				}
				result.add(c);
			} else {
				BUFFER.append(c);
			}
			PREVIOUS_CHAR = c;
		}
		return Collections.unmodifiableList(result);
	}
}

 

分享到:
评论

相关推荐

    Java实现四则混合运算代码示例

    主要介绍了Java实现四则混合运算代码示例,文中展示了详细代码,具有一定参考价值,需要的朋友可以了解下。

    加减乘除四则混合运算计算器-java

    设计GUI界面的计算器程序,用户可以通过鼠标依次输入参加计算的数值进行加、减、乘、除等混合运算功能。可参照windows平台上的计算器。 java 面向对象程序设计》课程设计

    利用堆栈编程实现四则混合运算

    利用堆栈编程实现四则混合运算,说得很详细,短小,挺容易理解的~

    编译原理课程设计实现四则混合运算

    该软件包括完整的词法分析、语法分析、语义分析、Java代码实现和汇编代码实现的四则混合运算,功能齐全,代码易懂。包括相关的工具ant

    基于Java-GUI的四则运算练习系统.rar

    该资源为基于Java的四则运算练习系统,用户可以在该系统进行练习,考试,查看错题,和进行算法小游戏。练习和考试可以选择难度,通过考试后会提升自己的能力等级,解锁更高难度的测试。练习和考试中错的题目将记载入...

    Java综合程序设计——计算器(实现运算符优先级的四则混合运算)

    一个计算器,有多种功能,如取对数、求平方根。最重要的是利用堆栈算法实现运算符优先级。

    基于Java实现(GUI)四则运算【100012412】

    本次实验采用结对编程方式,设计开发一个小学生四则运算练习软件,使之具有以下功能: 由计算机从题库文件中随机选择 20 道加减乘除混合算式,用户输入算式答案,程序检查答案是否正确,每道题正确计 5 分,错误不...

    四则运算JAVA计算器

    简单的JAVA计算器,能进行四则运算,有 括号,加了栈!

    Java图形界面小学生整数四则运算练习软件

    使用图形用户界面编写一个小学生整数四则运算练习软件。程序启动后,用户输入用户名,然后选择做什么运算(加、减、乘、除、混合)、做几位数的运算,再单击“开始做题”,之后计算机按要求随机生成10道题目,用户...

    输入字符串实现加减乘除四则运算(java)

    将近250行的算法 实现了通过字符串进行加减乘除四则运算 纯通过处理字符串和数组实现 希望能帮助大家: 例如:String input &quot;33+26 77+70&quot;; String result &quot;&quot;; try { result Account...

    中国矿业大学程序设计综合实践java四次作业第一次作业简单计算器

    1. 能够完成加减乘除四则运算(整数、小数) 2. 具备清空、退格功能 一、 拓展功能: 1. 能够记录计算的历史记录 2. 正负号功能 3. 支持带括号的运算 4. 平方根,立方根,任意次方根 5. 平方、立方、任意次方 6. ...

    四则混合元算计算器Java

    课堂作业。。简单的JAVA程序,包括四则运算。。。很好,汗强大,,来看看把,,

    Android混合运算计算器核心方法代码思路

    超详细注释的 Android计算器混合运算核心方法,实现思路。其他语言也可以了解借鉴。

    android 实现计算器加减乘除混合运算

    Android 实现计算器的加减乘除混合运算 可以对输入数字进行删除返回

    java正则实现解析算术表达式 (仅限+-*/和括号)

    java正则实现解析算术表达式 (仅限+-*/和括号)

    java 实现加减乘除的方法

    java 实现加减乘除的方法 java 实现加减乘除的方法

    javacc四则运算表达式计算器

    本程序实现一个四则混合运算,用户只需要输入四则混合运算表达式,程序自动计算, 可以一次计算一个表达式,也可以批量计算多行表达式,而且适合商业计算精度要求。 由于该程序依赖一个清屏功能cls.dll,使用32位win7...

    Java实现一个简单的计算器

    设计一个计算器,用户可通过鼠标依次输入参加计算的数值,进行加减乘除等混合运算,还有科学计算方法开方、求倒、百分比,可以进行清零、退格,还有相应的便利功能复制、粘贴。除此之外,应设计一个便于使用的图形...

    calculator_java实现计算器_

    带有可视化界面的简易计算器(1) 计算器应包含功能有:显示当前的...(2) 不需要实现混合运算功能,即键入类似“XXXPYY=”后显示结果即可,其中X和Y为数字键,P为运算键。(3) 界面颜色、字体、按键排布无需与上图一致。

    小学生四则运算

    该软件用于辅助训练小学生熟练掌握整数的四则运算。软件的功能如下: ①用户可以选择做什么运算(加、减、乘、除、混合),做几位数的运算,每次的出题数量,是否限定时间等。设定自动保存,可以多次使用,设定也...

Global site tag (gtag.js) - Google Analytics