`
苍山洱海
  • 浏览: 5033 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

数学表达式判断以及计算

阅读更多
最近一个题目需要自己计算一个字符串数学表达式的值, 所以大体研究了一下. 自己使用java实现

功能有:

1, 支持有小数点的计算

2, 支持带负号的计算

3, 支持带括号的计算

4, 支持参数计算



代码如下:
package on0911;

import java.util.Stack;

/**
 * 计算简单数学表达式的值
 * @author Administrator
 *
 */
public class Expression {

	private Stack<Double> data = new Stack<Double>();
	private Stack<Operator> operatorStack = new Stack<Operator>();
	private String exp;
	enum Op{
		JIA('+'), JIAN('-'), CHENG('*'), CHU('/');
		private char value;
		Op(char value) {
			this.value = value;
		}
		
		public char getValue() {
			return value;
		}
	}
	
	public Expression(String exp) {
		this.exp = exp.replace(" ", "");
	}
	
	
	public static void main(String[] args) {
		String expression = "-30 + 36* 2 / 4 -  1 * - 0.4   ";
		System.out.println("表达式结果是:" + new Expression(expression).doC());
	}
	
	/**
	 * 计算表达式的值
	 * @return
	 */
	public double doC() {
		inStack();
		
		/*当符号栈不为空的时候进行计算*/
		while (operatorStack.size() > 0) {
			Double re = ontStep(data, operatorStack);
			data.push(re);
		}
		
		return data.pop();//返回最后结果
	}
	
	/**
	 * 扫描表达式, 根据条件将表达式的内容进行简单计算, 然后入栈
	 */
	public void inStack() {
		if (exp.endsWith("+") || exp.endsWith("-") || exp.endsWith("*") || exp.endsWith("/")) {
			throw new RuntimeException("表达式有误!不能以运算符结尾");
		}
		
		/*循环所有字符, 判断后进行操作*/
		for (int i = 0; i < exp.length();) {
			char c = exp.charAt(i++);//取得第一个字符
			
			/*在是数字值的情况下, 或者是负号的情况下, 继续搜索后续的字符*/
			if ((c <= '9' && c >= '0') || c == '.' || (i == 1 && c == '-') 
					|| (i > 1 && isOperator(exp.charAt(i - 2)))) {
				String temp = c + "";
				
				/*所有后续字符, 组成规定的数值*/
				for (; i < exp.length();) {
					char c2 = exp.charAt(i++);
					if ((c2 <= '9' && c2 >= '0') || c2 == '.') {
						temp += c2;
					} else {
						break;//判断跳出条件时, 漏过一个字符, 这是因为最后一个字符应该是数字, 所以如果不是数字就不管他
					}
				}
				
				/*如果不是最后一个数值的话, 游标前移一位, 重新读取刚才漏过的字符*/
				if (i != exp.length()) {
					i--;
				}
				Double num = Double.parseDouble(temp);
				data.push(num);//将数据压入数据栈
			} else {
				if (isOperator(c)){
					Operator op = new Operator(c);
					if (operatorStack.size() == 0) {
						operatorStack.push(op);//运算符栈在空的时候直接入栈
					} else {
						Operator stackPop = operatorStack.pop();
						
						//比较运算符栈栈顶运算符和当前运算符的优先级
						//1, 如果大于栈顶运算符的优先级, 就直接入栈.
						//2, 小于或者等于的话, 就先计算数据栈和运算符栈的一次, 然后将结果压入数据栈. 
						//  然后将当前运算符压入运算符栈
						if (op.getPriority() > stackPop.getPriority()) {
							operatorStack.push(stackPop);
							operatorStack.push(op);
						} else {
							operatorStack.push(stackPop);
							Double re = ontStep(data, operatorStack);//计算一次
							data.push(re);//压结果入栈
							operatorStack.push(op);//当前运算符入栈
						}
					}
				} else {
					throw new RuntimeException(c + "符号错误");
				}
			}
		}
	}
	
	private boolean isOperator(char c) {
		if (Op.JIA.getValue() == c || Op.JIAN.getValue() == c || Op.CHENG.getValue() == c || Op.CHU.getValue() == c) {
			return true;
		}
		
		return false;
	}
	
	/**
	 * 将数据栈的数据提取两个和运算符栈的一个运算符进行计算, 且返回结果
	 * @param data2
	 * @param operatorStack2
	 * @return
	 */
	private Double ontStep(Stack<Double> data2, Stack<Operator> operatorStack2) {
		Double re = 0d;
		Double next = data2.pop();
		Double pre = data2.pop();
		Operator o = operatorStack.pop();
		re = cal(pre, o, next);//计算数据
		return re;
	}
	
	
	/**
	 * 计算得到值
	 * @param pre
	 * @param o
	 * @param next
	 * @return
	 */
	private Double cal(Double pre, Operator o, Double next) {
		if (o == null) {
			throw new RuntimeException("空操作符");
		}
		
		char cc = o.getOp();
		if (cc == Op.JIA.getValue()) {
			return new Double(pre + next);
		}
		
		if (cc == Op.JIAN.getValue()) {
			return new Double(pre - next);
		}
		
		if (cc == Op.CHENG.getValue()) {
			return new Double(pre * next);
		}
		
		if (cc == Op.CHU.getValue()) {
			return new Double(pre / next);
		}
		
		throw new RuntimeException("错误的运算符!");

	}


	/**
	 * 自定义的操作符类
	 * @author Administrator
	 *
	 */
	class Operator {
		char op;
		int priority;
		
		public Operator(char op) {
			this.op = op;
			switch (op) {
			case '+': priority = 5;break;
			case '-': priority = 5;break;
			case '*': priority = 6;break;
			case '/': priority = 6;break;
			default: throw new RuntimeException("错误的操作符");
			}
		}

		public char getOp() {
			return op;
		}

		public void setOp(char op) {
			this.op = op;
		}

		public int getPriority() {
			return priority;
		}

		public void setPriority(int priority) {
			this.priority = priority;
		}
		
		
	}
	
}


package on0911;

/**
 * 计算带括号的复杂表达式的值
 * @author Administrator
 *
 */
public class ComplexExpression {
	
	/**
	 * 计算给定字符串的表达式值
	 * @param str
	 * @return
	 */
	public double doD(String str) {
		String exp = str.replace(" ", "");//替换空字符
		int flag = 0;//标志括号位
		StringBuilder exp2 = new StringBuilder();//储存去除括号后的表达式
		
		/*扫描给定表达式字符串, 进行判断然后响应操作*/
		for (int i = 0; i < exp.length();) {
			char c = exp.charAt(i++);
			
			//碰到时左括号的时候, 标志位自加, 然后将此括号内的字符串进行计算得到数值后放到exp2中
			if (c == '(') {
				flag++;
				StringBuilder sb = new StringBuilder();//此括号内的字符串
				for (; i < exp.length();) {
					char c2 = exp.charAt(i++);
					sb.append(c2 + "");//添加字符
					//左括号自加, 右括号自减
					if (c2 == '(') {
						flag++;
					} else if (c2 == ')') {
						flag--;
					}
					
					/*碰到右括号时, 如果标志位确认是当前左括号的互补括号, 就进行递归计算此字符串的值*/
					if (c2 == ')' && flag == 0) {
						String temp = sb.substring(0, sb.length() - 1);
						temp = getValue(temp);//递归计算括号内的值
						exp2.append(temp);//将值添加到exp2字符串中
						break;
					}
				}
			} else {
				exp2.append(c);
			}
		}
		
		//System.out.println(exp2.toString());
		return new Expression(exp2.toString()).doC();//返回计算exp2值的数值
	}

	/**
	 * 递归计算给定字符串的值
	 * @param temp
	 * @return
	 */
	private String getValue(String temp) {
		temp = temp.replace(" ", "");
		if (!temp.contains("(")) {
			return new Expression(temp).doC() + "";//当不含有括号的时候,直接返回计算值
		}
		
		return doD(temp) + "";//有括号的时候就返回计算括号内得到的值
	}
	
	public static void main(String[] args) {
		//String str = "3 *- (1 - 2 / 4) + ( 1 + (2 - 3)) + 2";
		//System.out.println("答案是:" + new ComplexExpression().getValue(str));
		varTest();
	}
	
	public static void varTest() {
		int A = 2, B = 34;
		String str = "3 *- (A - 2 / 4) + ( 1 + (2 - B)) + 2";
		str = str.replace("A", A + "");
		str = str.replace("B", B + "");
		
		System.out.println("答案是:" + new ComplexExpression().getValue(str));
	}
}

分享到:
评论
1 楼 tangzililiang 2010-03-22  
表达式格式的检查严重不足!!!

相关推荐

    c++数学表达式解析

    在C++编程中,实现一个数学表达式解析器是一项常见的任务,它允许程序处理和求解用户输入的数学表达式。本项目旨在提供一个简单易懂的C++计算器实现,支持括号和基本的四则运算(加、减、乘、除)。通过使用波兰...

    论文研究-基于MathML的数学表达式等价性的研究.pdf

    MathML是一种基于XML的语言...总的来说,基于MathML的数学表达式等价性研究,是将数学知识、计算机科学中的算法理论以及XML技术相结合的产物,它的深入研究对于科学计算、在线教育、知识表达等多个领域都有重要的意义。

    数学表达式计算(c语言实现).doc

    数学表达式计算(C语言实现) 数学表达式计算是计算机科学中一个非常重要的领域,旨在实现对数学表达式的计算和评估。在本文中,我们将讨论两种常见的数学表达式计算算法:中缀转后缀算法和两个栈实现算法,并详细...

    Java计算数学表达式代码详解

    Java计算数学表达式的核心是将输入的字符串表达式转换为后缀表达式(逆波兰表示法),然后通过栈数据结构来计算表达式的值。这里,我们有两个关键的类:`Calculator`和`ArithHelperCalculator`,不过在提供的代码中...

    任意数学表达式计算 mfc

    标题中的“任意数学表达式计算 mfc”指的是使用MFC(Microsoft Foundation Classes)库来实现一个能够处理任意数学表达式的计算器。MFC是微软提供的一套C++类库,用于构建Windows应用程序,它封装了许多Windows API...

    字符串类型的数学表达式 不用解析 直接得出结果

    字符串类型的数学表达式 不用解析 直接得出结果 public class IllegalExpressionException extends RuntimeException { private static final long serialVersionUID = 7941685726759058059L; public ...

    易语言计算数学表达式源码

    在易语言中,计算数学表达式是一项基本且重要的功能,尤其对于处理科学计算、数据分析等任务时。本源码示例提供了如何在易语言中实现这一功能的详细步骤。 在易语言中,计算数学表达式通常涉及以下几个核心知识点:...

    Delphi表达式计算(用了这么多这个比较好)

    这些库可以处理复杂的数学表达式、逻辑表达式,甚至支持变量和函数。 总的来说,Delphi中的表达式计算涉及到对字符串表达式的解析、编译和执行,以及使用诸如IIF这样的构造来简化条件逻辑。通过理解这些概念和工具...

    计算数学表达式,支持小数

    计算数学表达式,+ - * /,扩展方便,可以判断表达式是否合理,可以计算小数的加减乘除运算

    表达式的自动计算

    【表达式的自动计算】是指计算机程序能够自动解析和计算数学表达式的过程。这一过程涉及到算法的设计和数据结构的运用,通常有两种主要实现方法。 **第一种方法:中缀表达式转后缀表达式再计算** 1. **中缀转后缀*...

    联机手写数学表达式识别方法综述

    ### 联机手写数学表达式识别方法综述 #### 一、引言与背景 数学表达式作为科学和工程技术领域的重要组成部分,在各种科技文献中占有核心地位。随着信息技术的发展,尤其是互联网技术的进步,如何高效地将这些数学...

    利用堆栈实现数值表达式的计算

    在这个场景中,“利用堆栈实现数值表达式的计算”是指通过堆栈来解决数学表达式的求值问题,如给定的示例3×5-2+3×8/2,它涉及到加法(+)、减法(-)、乘法(×)、除法(/)以及括号((和))的运算。...

    calculator:Javascript的数学表达式解析器

    计算器Javascript的数学表达式解析器。 可在微信小程序中使用支持IE9 + 支持AMD / CommonJS 支持定制运营商支持自定义功能您可以使用util将数学表达式解析为反向波兰表示法或对其求值。例如,当解析1+2*3 ,您将获得...

    数学、布尔表达式计算.zip

    《布尔表达式计算及其在数学中的应用》 布尔表达式计算是计算机科学中一个基础而重要的概念,尤其在逻辑运算和编程领域具有广泛的应用。它源于19世纪英国数学家乔治·布尔的工作,布尔数学是现代计算机科学的理论...

    STL-后缀表达式的计算

    本文将详细介绍如何利用C++标准模板库(STL)中的容器与算法实现后缀表达式的计算,并且支持包括括号在内的复杂数学表达式。文章的核心内容包括: 1. **后缀表达式的概念**:了解什么是后缀表达式(也称为逆波兰表示...

    数学表达式的求值算法实现(加减乘除及平方的混合运算)

    这个任务涉及到解析和执行包含加法、减法、乘法、除法以及平方等运算的数学表达式。在这个场景下,我们讨论的是使用C++语言来实现这样一个功能。C++是一种强类型、面向对象的编程语言,它提供了丰富的库函数和自定义...

    字符串转换为计算公式的若干种方法

    这在编程、计算器应用程序、电子表格软件以及任何涉及解析用户输入的数学表达式并执行计算的场景中都非常有用。 ### 关键知识点 #### 1. **解析数学表达式** 解析数学表达式是将字符串形式的数学运算转换成计算机...

    复杂逻辑表达式的计算

    首先,逻辑表达式是一种用于判断条件真假的数学表达式,它由逻辑运算符连接起来的布尔变量或其表达式组成。在给定的例子中,表达式为`(A&!B)&((!A&C)|!C)`,其中`&`代表逻辑与(AND),`|`代表逻辑或(OR),`!`代表...

Global site tag (gtag.js) - Google Analytics