`

java四则运算-通过逆波兰式求值

    博客分类:
  • java
阅读更多
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;

/*
 *测试 -5*(10/(2*4.5-4)+(-3/1.5+4)*(-2))/(-2/1-(-1))+12=2.0
 */
public class Calc {
	// 求四则运算表达式运算结果
	public static double excute(String value) throws Exception {
		List<String> list = toList(value);// 按顺序转成数字符号list 即中序表达式
		list = toSuffixExpressionList(list);// 转成逆波兰式数字符号list 即后序表达式
		double result = suffix_excute(list);// 求逆波兰式结果
		System.out.println(value + "=" + result);
		return result;
	}

	// 表达式划分成中序list 即从左到右数字符号分开
	private static List<String> toList(String value) {
		// 开始为-时加上0
		if ("-".equals(value.substring(0, 1))) {
			value = "0" + value;
		}
		int begin = 0;
		int end = 0;
		String item;
		List<String> resultList = new ArrayList<String>();
		for (int i = 0, len = value.length(); i < len; i++) {
			item = value.substring(i, i + 1);
			if (isOperator(item)) {
				// 负数跳过
				if ("-".equals(item) && "(".equals(value.substring(i - 1, i))) {
					continue;
				}
				end = i;
				// 前一个非符号时加上数字
				if (begin != end) {
					resultList.add(value.substring(begin, end));
				}
				// 加上符号
				resultList.add(value.substring(end, end + 1));
				begin = end + 1;
			}
		}
		// 加上最后一个数字
		if (begin != value.length()) {
			resultList.add(value.substring(begin));
		}
		// System.out.println(value + "=" + list);
		return resultList;
	}

	// 中序list转换成逆波兰式list 左右根
	private static List<String> toSuffixExpressionList(List<String> list) throws Exception {
		Stack<String> operatorStack = new Stack<String>();// 符号栈
		Stack<String> resultStack = new Stack<String>();// 结果栈
		Iterator<String> iter = list.iterator();
		while (iter.hasNext()) {
			String item = iter.next();
			if (isOperator(item)) {
				if (")".equals(item)) {
					// 遇到)时符号栈一直弹出并压入结果栈直到遇到(,弹出(废弃,结束。
					while (!(operatorStack.isEmpty() || "(".equals(operatorStack.peek()))) {
						resultStack.push(operatorStack.pop());
					}
					// 弹出(
					if (!operatorStack.isEmpty() && "(".equals(operatorStack.peek())) {
						operatorStack.pop();
					} else {
						throw new Exception("(少了");
					}
				} else if ("(".equals(item)) {
					// 遇到(时直接入符号栈,结束
					operatorStack.push(item);
				} else {
					// 遇到其他运算符时与符号栈顶(若符号栈顶为空或(时直接入符号栈,结束)运算比较 若比栈顶高直接入符号栈,结束
					// 否则符号栈弹出并压入结果栈 并再执行与符号栈顶比较直到弹入符号栈,结束
					while (!(operatorStack.isEmpty() || "(".equals(operatorStack.peek()))) {
						if (compareOperator(item, operatorStack.peek()) < 1) {
							resultStack.push(operatorStack.pop());
						} else {
							break;
						}
					}
					operatorStack.push(item);
				}

			} else {
				// 数字时直接入结果栈
				resultStack.push(item);
			}
		}
		// 符号栈全部弹出并压入结果栈
		while (!operatorStack.isEmpty()) {
			if ("(".equals(operatorStack.peek())) {
				throw new Exception("(多了");
			}
			resultStack.push(operatorStack.pop());
		}
		// 结果栈弹出并反序得出最终结果
		iter = resultStack.iterator();
		List<String> resultList = new ArrayList<String>();
		while (iter.hasNext()) {
			resultList.add(iter.next());
		}
		// System.out.println(list + "=" + rtList);
		return resultList;
	}

	// 逆波兰式list 求值
	// 从左至右扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(次顶元素 op
	// 栈顶元素),并将结果入栈;重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果。
	private static double suffix_excute(List<String> list) {
		Stack<Double> resultStack = new Stack<Double>();
		Iterator<String> iter = list.iterator();
		Double num1;
		Double num2;
		while (iter.hasNext()) {
			String item = iter.next();
			if (isOperator(item)) {
				num2 = resultStack.pop();
				num1 = resultStack.pop();
				resultStack.push(doOperator(num1, num2, item));
			} else {
				resultStack.push(Double.parseDouble(item));
			}
		}
		return resultStack.pop();
	}

	// 比较两运算高低 1 1>2, 0 1=2 -1 1<2
	private static int compareOperator(String operator1, String operator2) {
		if ("*".equals(operator1) || "/".equals(operator1)) {
			return ("-".equals(operator2) || "+".equals(operator2)) ? 1 : 0;
		} else if ("-".equals(operator1) || "+".equals(operator1)) {
			return ("*".equals(operator2) || "/".equals(operator2)) ? -1 : 0;
		}
		// 这个到不了
		return 1;
	}

	// +-*/基本运算
	private static double doOperator(Double num1, Double num2, String operator) {
		if ("+".equals(operator)) {
			return num1 + num2;
		} else if ("-".equals(operator)) {
			return num1 - num2;
		} else if ("*".equals(operator)) {
			return num1 * num2;
		} else if ("/".equals(operator)) {
			return num1 / num2;
		}
		// 这个到不了
		return -1;
	}

	// 是否为运算符
	private static Boolean isOperator(String value) {
		return "(".equals(value) || ")".equals(value) || "+".equals(value) || "-".equals(value) || "*".equals(value)
				|| "/".equals(value);
	}

	public static void main(String[] args) {
		try {
			excute("-5*(10/(2*4.5-4)+(-3/1.5+4)*(-2))/(-2/1-(-1))+12");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

结果
-5*(10/(2*4.5-4)+(-3/1.5+4)*(-2))/(-2/1-(-1))+12=2.0
2
2
分享到:
评论

相关推荐

    四则运算求值(中缀转逆波兰式)

    标题 "四则运算求值(中缀转逆波兰式)" 涉及到的是计算机科学中的算法问题,主要集中在表达式求值和转换方法上。逆波兰表示法(Reverse Polish Notation,RPN),也被称为后缀表示法,是一种没有括号的数学表达式...

    java带逆波兰式的科学计算器

    逆波兰式科学计算器是一种基于后缀表达式的计算工具,它在计算过程中避免了括号的使用,通过将运算符置于其操作数之后来简化表达式。这种计算器在计算机科学领域中有着广泛的应用,特别是在编译原理和算法设计中。...

    java实现逆波兰式运算

    1.本例是对数据结构栈的练习 2.本例使用了java类集作为辅助,但不是必要,所有功能都可以自己实现 3.本例有输入四则运算的合法性判断方法,是基于逻辑实现,可以使用正则表达式字符匹配,会是代码简洁不少.

    布尔翻译逆波兰式,完整实验报告,写上班级姓名即可

    布尔翻译逆波兰式是一种在计算机科学中用于表示布尔表达式的计算方法,它是逆波兰表示法(也称为后缀表示法)的一个特例,主要用于布尔代数的运算。在这个实验报告中,我们将深入探讨这一概念,并了解如何将其应用于...

    java控制台四则运算计算程序源码

    Java控制台四则运算计算程序源码是一种基于Java编程语言实现的简单计算器,它能够处理任意长度的符合四则运算规则的数学表达式。在控制台上进行交互式操作,用户可以输入数学公式,程序会进行解析并计算出结果。这个...

    Android 带滑动、抽屉效果的逆波兰式计算器

    4. **四则运算**:计算器的核心功能,包括加法、减法、乘法和除法。在逆波兰式计算过程中,需要处理这些基本的数学运算。例如,遇到"+"时,取出栈顶的两个数相加,结果再入栈;同理,"-"、"*"和"/"分别对应减法、...

    安卓抽屉效果相关-带抽屉滑动效果使用ViewPager滑动页面使用逆波兰式对表达式进行计算支持四则运算.rar

    最后,提到的是“逆波兰式对表达式进行计算”。逆波兰表示法(Reverse Polish Notation, RPN)是一种后缀表达式,它消除了括号的使用,通过操作数和操作符的顺序来表示计算。在RPN中,操作数先于操作符出现,比如在...

    数据结构课设--四则运算练习软件

    栈可以用来实现运算表达式的后缀表示法(也称为逆波兰表示法),从而简化四则运算的求解过程;队列则可能在处理用户输入的运算请求时发挥作用,保证先进先出的顺序。 其次,四则运算的实现涉及到算法的设计。加、减...

    js库实现中缀表达式(即日常使用的四则运算表达式)转换成后缀表达式(逆波兰式),方便计算机计算

    然而,计算机处理这种表达式时不如处理后缀表达式(逆波兰式)来得直接。后缀表达式是将运算符放在操作数之后的形式,例如,上述中缀表达式对应的后缀表达式为 \(2 3 4 * +\)。这样的表示方式使得求值过程无需使用栈...

    victory.zip

    - **扩展运算符集**:除了基本的四则运算,还可以支持开方、指数等复杂运算。 - **处理浮点数**:扩展数据类型以支持浮点数的运算。 - **括号处理**:正确处理括号,确保运算顺序的准确性。 通过这个“victory....

    带抽屉滑动效果

    在编程中,逆波兰式通常用于实现计算器功能,例如这里提到的"支持四则运算"。四则运算包括加法、减法、乘法和除法,是任何基础计算器的基础。 为了实现这样的功能,开发者可能需要编写一个解析器,将用户输入的中缀...

    算术表达式的求值数据结构课程设计

    4. **后缀表示法(逆波兰表示法)**:为了简化计算,可以将表达式转换为后缀表示法。在这种表示法中,运算符位于它们的操作数之后,避免了需要考虑运算符优先级的问题。可以使用栈来实现从普通中缀表达式到后缀...

    android计算器 可直接运算简单的代数式

    本项目名为“android计算器”,它具有处理基本的四则运算以及简单的代数式输入的功能。以下将详细讲解这个计算器应用的核心知识点。 首先,我们要理解Android应用程序的基本架构。在Android开发中,我们通常会使用...

    java实现简单的计算器

    在这个项目中,我们主要使用了Swing和AWT两个库来创建用户界面,并实现了基本的四则运算以及求相反数的功能。下面将详细介绍这些知识点。 **1. Swing与AWT:** Swing和AWT是Java提供的两种用于构建桌面应用程序GUI...

    仿windoes计算器

    这可能涉及到栈数据结构的运用,因为计算四则混合表达式通常采用逆波兰表示法(RPN)或中缀表达式的转换。 4. **错误处理**:计算器应该能处理各种异常情况,比如除以零、输入非法字符等。良好的错误处理机制可以...

    京东2016实习生招聘笔试真题-技术岗位选择题一.docx

    - 后缀表达式(逆波兰表示法)遵循特定的计算规则,即从左至右依次计算操作数和运算符。 - 对于给定的后缀表达式532+*82/-,先计算括号内的表达式再进行后续操作。 ### 12. 单链表的基本操作 - **知识点**: - ...

    IKExpressoin简易表达式引擎V2.1.0使用说明

    IKExpression 采用了逆波兰式算法结合指针栈优化来实现高效的表达式解析。它主要由以下四个部分组成: - **表达式编译**:将用户输入的表达式转换成可执行的内部数据结构。 - **表达式执行**:根据编译后的数据结构...

    Android 之计算器源码

    【Android之计算器源码】是一个基于Android 4.2.2版本开发的简易计算器应用,主要功能是实现基本的四则运算,同时支持带有括号的复杂表达式的计算。这个项目对于初学者来说是一个很好的实践案例,因为它涵盖了...

    OPGComplete.zip_编译器/解释器_Java_

    四元式是另一种表示程序结构的方式,它通常用于中缀表达式的逆波兰表示(后缀表达式)转换。一个四元式包含四个部分:操作数、操作符、结果和附加信息。例如,四元式 "a+b=c" 可以表示为 (a, b, +, c),其中 "+" 是...

    编译原理复习大纲 编译原理主要内容

    25. **逆波兰表示法**、**三元式**和**四元式**:中间代码表示形式,用于简化表达式求值,逆波兰表示法无需括号,三元式和四元式分别以三元和四元组合表示操作。 26. **画出栈式存储分配示意图**:在静态存储分配中...

Global site tag (gtag.js) - Google Analytics