`

java实现四则混合运算

阅读更多

  最近在看数据结构。想要实现四则混合运算。用栈来实现。

  去网上看了好些代码(想偷懒来着)结果代码都不全。思路不清晰。

  看的难受,最后觉得还是自己写吧。学习嘛,偷懒不得。

  栈的本质就是个线性表。结构就是个后进先出的胡同。只能操作线性表表尾元素的插入和删除。

  

  下面是对栈的实现。这些基本是照搬别人的。

package stack;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 栈的实现,先进后出。
 */
public class Stack {
	// 初始化数组
	public String[] stackArr = new String[16];
	// 栈的顶部
	int top = -1;

	// 出栈操作
	public String pop() {
		return stackArr[top--];
	}

	// 进栈操作
	public void push(String c) {
		// 原数组满了,就扩容1.5倍
		if (isFull()) {
			resize();
		}
		stackArr[++top] = c;
	}
	
	// 清空栈
    public void clear() {     
    	stackArr = null;     
    	top = -1;     
    }   

    // 栈的元素个数
    public int length() {     
        return top + 1;     
    }   
	// 判断栈是否为空
	public boolean isEmpty() {
		return top == -1;
	}

	// 判断栈是否已满
	public boolean isFull() {
		return top == stackArr.length - 1;
	}

	// 取栈顶元素
	public String peek() {
		return stackArr[top];
	}

	/**
	 * 数组扩容,1.5倍长度
	 */
	private void resize() {
		String[] temp = new String[stackArr.length * 3 / 2 + 1];
		for (int i = 0; i < stackArr.length; i++) {
			temp[i] = stackArr[i];
		}
		stackArr = temp;
	}

	public void print (){
		for (int i = 0; i <= top; i++) {
			 System.out.print(stackArr[i]);
		}
	}

}

    

   这里需要讲一下四则混合运算的步骤,

   先科普一下后缀表达式:它是波兰的一个哥们想出来的。名字太长不好记,就被后人称为逆波兰表达式了。

   中缀表达式:9+ (3-1) * 3+10/ 2

   后缀表达式:931一3 * +102/+

 

   1,将中缀表达式转化为后缀表达式(逆波兰表达式Reverse Polish Notation)

            规则:从左到右遍历表达式的每个数字和符号,遇到是数字就进栈,遇到是符号,就将处于栈顶两个数字出栈,进行运算,运算结果进栈, 一直到最终获得结果

    2,将后缀表达式进行运算得出结果

           规则:从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后缀表达式的一部分 i 若是符号,则判断其与栈顶符号的优先级,是右括号或优先级低于栈顶符号(乘除优先加减)则栈顶元素依次出栈并输出 , 并将当前符号进栈,一直 到最终输出后缀表达式为止。

 

  下面是我自己对四则混合运算的实现。写的时候小坑比较多。你们自己写过就知道了。

package stack;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;

/**
 * 四则混合运算<br/>
 * 支持小数运算,支持带负数运算。
 */
public class Operation {
	// 栈
	static Stack stack = new Stack();

	public static void main(String[] args) {
//		 String jisuan = "-9*(9+2+(-1)+7)";
		 String jisuan = "-9+(9+(3-1)*3.13+1.2/2+(7-2))";
//		String jisuan = "9+(1-3)*3+10/2";

		// 做处理:剔除空格,将中文的括号统一替换成英文的
		jisuan = replaceStr(jisuan);
		
		// 计算公式字符串处理成集合
		List<String> arry = stringToList(jisuan);

		// 中缀表达式处理为后缀表达式
		List<String> end = CenToEnd(arry);

		// 计算结果
		String result = Opera(end);
		System.out.println(result);
		
		
		// 写#的是有值就写值,没值就不写	DecimalFormat df=new DecimalFormat("#.000");
		// 写0的是有值就写值,没值就写0	DecimalFormat df=new DecimalFormat("0.000");
		double d = Double.parseDouble(result);
		DecimalFormat df=new DecimalFormat("0.00");
		String d2 = df.format(d);
		System.out.println(d2);

		// 开始计算数值

	}

	/**
	 * 计算结果<br/>
	 * 是数字,就进栈,<br/>
	 * 是字符,就把栈顶值取出,根据字符进行运算,然后再放入到栈中,一直到把集合遍历结束为止
	 * @param end 后缀运算表达式List集合
	 * @return 运算结果
	 */
	private static String Opera(List<String> end) {

		double first = 0;
		double second = 0;

		for (String str : end) {
			try {
				// 如果是数字,将不会抛异常,如果不是,那么将会走catch部分。
				Double.parseDouble(str);
				stack.push(str);
			} catch (Exception e) {
				double result = 0;
				// 不是数字

				// 如果栈中是1,2,3 符号是 - ,原来的公式是 2-3=-1
				// second = 3, first = 2 
				// 位置颠倒后,就变成了second = 3, first = 2 公式就变成了3-2=1
				// 所以下面两行代码顺序不能颠倒
				second = Double.parseDouble(stack.pop());
				first = Double.parseDouble(stack.pop());

				// 计算
				if (str.equals("+")) {
					result = first + second;
				} else if (str.equals("-")) {
					result = first - second;
				} else if (str.equals("*")) {
					result = first * second;
				} else {// 除
					result = first / second;
				}

				// 将每次运算完的结果再次放到栈顶
				stack.push(result + "");
			}

		}
		// 取出栈顶的值,也就是最后的运算结果
		return stack.peek();
	}

	/**
	 * 容错处理:处理空格,中文括号。
	 * 
	 * @param str 输入的运算表达式字符串
	 * @return
	 */
	private static String replaceStr(String str) {

		str = str.replace(" ", "");
		str = str.replace("(", "(");
		str = str.replace(")", ")");
		str = str.replace("。", ".");
		String[] strArr = str.split("=");
		return strArr[0];
	}

	/**
	 * 中缀表达式处理为后缀表达式<br/>
	 * 遍历中缀表达式,是数字,就添加到后缀表达式的list中。<br/>
	 * 				是符号,就判断与栈顶符号的优先级。是右括号“)”或者优先级低于栈顶符号,<br/>
	 * 				栈顶元素就依次输出到后缀表达式的list,并将当前符号入栈。
	 * @param arry 中缀运算表达式List集合
	 * @return	后缀表达式list集合
	 */
	private static List<String> CenToEnd(List<String> arry) {
		// 后缀表达式集合
		List<String> end = new ArrayList<String>();
		for (String c : arry) {

			// 是数字就添加到
			if (StringUtils.isNumeric(c)) {
				end.add(c);
				continue;
			}

			// 判断和栈顶符号的优先级
			if (isPriority(c)) {
				stack.push(c);
			} else {
				// 当前值C优先级低于栈顶,并且C是右括号“)”
				// 栈顶符号依次出栈。取出来的栈顶值加入list
				if (c.equals(")")) {
					while (!stack.isEmpty()) {
						// 栈顶出栈
						String topValue = stack.pop();
						if (topValue.equals("(")) {
							break;
						}
						// 栈顶值加入后缀表达式集合
						end.add(topValue);
					}
				} else {
					// 当前值C优先级低于栈顶,栈顶符号出栈,C进栈。取出来的栈顶值加入list					
					// 栈顶出栈
					String topValue = stack.pop();
					// 栈顶值加入后缀表达式集合
					end.add(topValue);
					stack.push(c);
				}
			}

		}

		// 添加最后栈中剩下的元素
		while (!stack.isEmpty()) {
			end.add(stack.pop());
		}
		return end;
	}

	/**
	 * 判断c和栈顶符号的优先级:右括号或者优先级低于栈顶符号,栈顶符号以此出栈输出,并将当前符号进栈,<br/>
	 * 
	 * @param c
	 * @return true:当前值C优先栈顶,C进栈. <br/>
	 *         false:当前值C低于栈顶,栈顶符号出栈,C进栈。
	 */
	public static boolean isPriority(String c) {

		// 空栈,c进栈
		if (stack.isEmpty()) {
			return true;
		}

		// 右括号,栈顶依次出栈,直到匹配到最近的左括号(
		if (c.equals(")")) {
			return false;
		}

		// 左括号( 一律进栈。不比较优先级 
		if (c.equals("(")) {
			return true;
		}

		// 栈顶值
		String topValue = stack.peek() + "";

		// 优先级:左括号(  > (乘 = 除) >(加 = 减)> 右括号)
		if (topValue.equals("+") || topValue.equals("-")) {
			if (c.equals("*") || c.equals("/")) {
				return true;
			} else {
				return false;
			}
		} else {
			if (topValue.equals("/") || topValue.equals("*")) {
				if (c.equals("+") || c.equals("-")) {
					return false;
				} else {
					return true;
				}
			} else {
				// 能走到这里,只剩下( 了。优先级它最低
				return true;
			}
		}
	}

	/**
	 * 将计算公式字符串变成list,也就是需要使用的中缀表达式的list形式<br/>
	 * 需要处理小数点和负数的情况
	 * @param str
	 * @return 中缀表达式list集合
	 */
	public static List<String> stringToList(String str) {
		// String str = "-9+(3-1)*3+10.5/2+4*5-2";
		char[] arry = str.toCharArray();
		// 字符串缓存
		StringBuilder builder = new StringBuilder();
		// 字符串处理后的集合
		List<String> list = new ArrayList<String>();

		for (int i = 0; i < arry.length; i++) {

			// 是数字就存到缓存中,如果循环的下个元素还是数字,就将其添加到缓存字符串后面。
			// 如果是带小数的数,也要收集完整
			if (StringUtils.isNumeric(arry[i] + "") || ".".equals(arry[i] + "")) {

				// 如果是循环的最后一位,就直接添加到缓存中
				if (i == arry.length - 1) {
					list.add(arry[i] + "");
					continue;// 有没有无所谓,后面的builder添加了元素也没人再用它了。
				}
				builder.append(arry[i]);
				continue;
			} else {
				// 如果<0,就不要向list中添加空了
				// 如果>0,说明上一轮循环结束,已经搜集到了完整的数字。添加到list中
				if (builder.length() > 0) {
					list.add(builder.toString());
				}

				// 当公式最前面有负数时的处理
				// 例如:-9+(3-1)*3+10/2+(7-2)
				if (i == 0 && (arry[i] + "").equals("-")) {
					list.add("0");
					list.add("-");
					continue;
				}
				
				// 如果公式中间带负数时的处理
				// 例如:-9+(-2)*3+10/2+(7-2)
				if((arry[i] + "").equals("-") && list.get(list.size()-1).equals("(")){
					list.add("0");
					list.add("-");
					continue;
				}

				list.add(arry[i] + "");

				// 为下一次循环做准备,清空内容
				builder = new StringBuilder();
			}

		}
		return list;
	}
}

 

 

 

 

分享到:
评论

相关推荐

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

    Java实现四则混合运算代码示例 Java是目前最流行的编程语言之一,广泛应用于Android应用开发、Web开发、企业软件开发等领域。四则混合运算是数学运算中最基本的运算,包括加法、减法、乘法和除法。Java实现四则混合...

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

    在本项目中,我们主要探讨的是如何利用Java编程语言设计一个具有加减乘除四则混合运算功能的GUI(图形用户界面)计算器。这个计算器旨在模拟Windows操作系统中的标准计算器,提供用户友好的交互方式,使得非程序员也...

    Java计算器 四则混合运算

    ### Java计算器实现:四则混合运算解析 在深入解析给定的Java代码片段之前,我们首先需要理解其核心功能——实现一个能够处理包含加、减、乘、除四则混合运算的计算器。此计算器接收一个混合运算表达式作为输入,并...

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

    总结来说,"编译原理课程设计实现四则混合运算"项目提供了一个全面的实践平台,让学生们能够亲手操作编译器的各个关键步骤,从词法分析到语义分析,再到Java代码和汇编代码的生成。通过这样的实践,学习者可以深入...

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

    在本项目中,"Java综合程序设计——计算器(实现运算符优先级的四则混合运算)"是一个典型的软件开发任务,旨在实现一个功能丰富的计算器,包括基础的四则运算以及更复杂的数学操作如对数和平方根。这个计算器的关键...

    Java版计算器支持四则混合运算.+-*/()

    在编程领域,构建一个能处理四则混合运算的计算器是一项基础但重要的任务。在这个Java实现的版本中,我们关注的核心知识点主要包括:基本算术运算符、运算符优先级、小数点处理以及程序设计的基本结构。 首先,让...

    基于Java实现四则运算题目生成程序.zip

    【Java实现四则运算题目生成程序】 在编程领域,创建一个能够自动生成四则运算题目的程序是一项常见的任务,尤其适用于教育和学习环境。在这个基于Java的课程设计中,我们探讨了如何利用Java语言实现这样的功能。...

    四则混合运算器

    四则混合运算是数学中的基本概念,涉及到加法、减法、乘法和除法的组合运用。在编程领域,创建一个四则混合运算器,尤其是针对移动平台如Android的应用,意味着开发一个能够处理这些运算的软件工具。下面将详细讨论...

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

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

    简单计算器四则混合运算

    本程序是一个简易的四则混合运算计算器实现,采用Java Swing库构建GUI界面。它支持加、减、乘、除以及数字输入等基本功能,并能进行简单的混合运算。 #### 二、核心组件与变量 1. **arg**: 用于存储计算过程中的...

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

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

    四则运算JAVA计算器

    该项目是一个基于Java Swing的简单计算器应用程序,能够实现基本的四则运算功能,并且支持括号操作,以解决优先级问题。为了处理复杂的数学表达式,该计算器还引入了栈的概念。 #### 二、项目结构与组件分析 1. **...

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

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

    简单的JAVA四则运算

    对于Java这样的面向对象语言而言,实现四则运算不仅涉及到基本的数据类型操作,还需要考虑到运算顺序以及异常处理等问题。 #### 二、Java程序结构与流程 根据提供的部分代码,可以了解到这是一个用于接收用户输入并...

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

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

    java 四则运算计算器

    **标题与描述解析:**“Java四则运算计算器”是一款基于Java语言开发的计算器应用,能够执行加、减、乘、除等基本算术运算,并支持混合运算,具备友好的用户界面。描述中强调了该计算器的易用性和简洁性,适合日常...

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

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

    简单的JAVA四则运算.pdf

    JAVA四则运算的实现与优化 本文将对 JAVA 四则运算的实现进行详细的分析与解释,并对代码进行逐行解释。 一、 JAVA四则运算的实现 在 JAVA 中,四则运算的实现可以使用基本的运算符和数据类型来实现。在本文中,...

Global site tag (gtag.js) - Google Analytics