包含简单科学运算的表达式求值
来源:互联网 发布:网络应急协调中心待遇 编辑:程序博客网 时间:2024/05/17 02:30
包含简单科学运算的表达式求值
想写个计算器,但又没有在网上找到直接可用的开源代码,于是自己试着捣鼓一下,写了这个工具类。
源代码
package mc.math;import java.math.BigDecimal;import java.util.Stack;/** * @author 明明 * <p> * 这个类用来计算算术表达式,返回计算的结果 * <p> * 支持以下运算符号: * <p> * +(加), -(减), *(乘), /(除), ((左括号), )(右括号), ^(幂), ²(平方), ³(立方), * <p> * sin(正弦), cos(余弦), tan(正切), ln(e为底的对数), log(10为底的对数), !(阶乘), √(根号) * <p> * 支持以下常量: * <p> * π(圆周率), e(自然常数) */public class Calculator { // s表示sin,c表示cos, t表示tan, l表示ln, o表示log, ~表示负号 private static final char ADD = '+'; private static final char SUBTRACT = '-'; private static final char MINUS = '~'; // 负号 private static final char MULTIPLY = '*'; private static final char DIVIDE = '/'; private static final char LEFT_PARENTHESIS = '('; private static final char RIGHT_PARENTHESIS = ')'; private static final char POW = '^'; private static final char POW2 = '²'; private static final char POW3 = '³'; private static final char SIN = 's'; private static final char COS = 'c'; private static final char TAN = 't'; private static final char LN = 'l'; private static final char LOG = 'o'; private static final char FACTORIAL = '!'; private static final char SQRT = '√';// private static final char PI = 'π';// private static final char E = 'e'; private static final char COMMA = ','; private Stack<Character> operatorStack; private Stack<String> operandStack; private static Calculator calculator = null; private Calculator() { operatorStack = new Stack<Character>(); operandStack = new Stack<String>(); } private static void initCalculator() { // Use singleton pattern(单例模式) if (calculator == null) { synchronized (Calculator.class) { if (calculator == null) calculator = new Calculator(); } } calculator.operatorStack.clear(); calculator.operatorStack.push(COMMA); calculator.operandStack.clear(); } /** * 计算算术表达式并返回计算结果 * @param expression 算术表达式 * @return 算术表达式的结果 */ public static String calculateExpression(String expression) { initCalculator(); expression = expression.replaceAll("sin", "s") .replaceAll("cos", "c") .replaceAll("tan", "t") .replaceAll("ln", "l") .replaceAll("log", "o") .replaceAll("π", String.valueOf(Math.PI)) .replaceAll("e", String.valueOf(Math.E)); int currentIndex = 0; int count = 0; char peekOperator; while (currentIndex < expression.length()) { char currentChar = expression.charAt(currentIndex); // 右结合单目运算符直接入符号栈 if (isUnaryOperator(currentChar)) { calculator.operatorStack.push(currentChar); currentIndex++; // 左结合单目运算符直接运算 } else if (currentChar == FACTORIAL || currentChar == POW2 || currentChar == POW3) { String result = calculate(calculator.operandStack.pop(), currentChar); calculator.operandStack.push(result); currentIndex++; } else if (isBinaryOperator(currentChar)) { // 双目运算符 // 检查是否是负号,负号是右结合单目运算符,直接入符号栈 if (currentChar == SUBTRACT) { if (currentIndex == 0 || isOperator( expression.charAt(currentIndex - 1))) { calculator.operatorStack.push(MINUS); currentIndex++; continue; } } peekOperator = calculator.operatorStack.peek(); while (peekOperator != COMMA) { // 如果前一个运算符是右结合单目运算符 if (isUnaryOperator(peekOperator)) { String result = calculate(calculator.operandStack.pop(), calculator.operatorStack.pop()); calculator.operandStack.push(result); // 如果前一个运算符是双目运算符,并且其优先级大于等于当前运算符的优先级 } else if (compareOperatorPriority(currentChar, peekOperator) <= 0) { binaryCalculate(); } else { break; } peekOperator = calculator.operatorStack.peek(); } calculator.operatorStack.push(currentChar); currentIndex++; } else if (currentChar == LEFT_PARENTHESIS) { // 左括号"("直接入符号栈 calculator.operatorStack.push(currentChar); currentIndex++; } else if (currentChar == RIGHT_PARENTHESIS) { // 右括号 ) peekOperator = calculator.operatorStack.peek(); while (peekOperator != LEFT_PARENTHESIS) { // 如果前一个运算符是右结合单目运算符 if (isUnaryOperator(peekOperator)) { String result = calculate(calculator.operandStack.pop(), calculator.operatorStack.pop()); calculator.operandStack.push(result); // 如果前一个运算符是双目运算符 } else { binaryCalculate(); } peekOperator = calculator.operatorStack.peek(); } calculator.operatorStack.pop(); currentIndex++; // 如果是数字 } else { do { count++; if (currentIndex + count >= expression.length()) break; } while (isDigitOrPoint(expression.charAt(currentIndex + count))); calculator.operandStack.push( expression.substring(currentIndex, currentIndex + count)); currentIndex += count; count = 0; } } peekOperator = calculator.operatorStack.peek(); while (peekOperator != COMMA) { // 如果前一个运算符是右结合单目运算符 if (isUnaryOperator(peekOperator)) { String result = calculate(calculator.operandStack.pop(), calculator.operatorStack.pop()); calculator.operandStack.push(result); // 如果前一个运算符是双目运算符 } else { binaryCalculate(); } peekOperator = calculator.operatorStack.peek(); } return removerRedundantZero(calculator.operandStack.pop()); } // 去除小数点后多余的0 private static String removerRedundantZero(String s) { if (s.contains(".")) { int startIndex = s.indexOf('.') - 1; for (int i = startIndex + 2, sLength = s.length(); i < sLength; i++) { if (s.charAt(i) != '0') { startIndex = i; } } return s.substring(0, startIndex + 1); } return s; } // 双目运算 private static void binaryCalculate() { String n2 = calculator.operandStack.pop(); String n1 = calculator.operandStack.pop(); String result = calculate(n1, n2, calculator.operatorStack.pop()); calculator.operandStack.push(result); } private static boolean isOperator(char c) { // s表示sin,c表示cos, t表示tan, l表示ln, o表示log, ~表示负号 return (c == ADD || c == SUBTRACT || c == MULTIPLY || c == DIVIDE || c == POW || c == SIN || c == COS || c == TAN || c == LN || c == LOG || c == SQRT); // π } // 判断是否是右结合单目运算符,是则返回true private static boolean isUnaryOperator(char c) { return (c == MINUS || c == SIN || c == COS || c == TAN || c == LN || c == LOG || c == SQRT); } // 判断是否是双目运算符,是则返回true private static boolean isBinaryOperator(char c) { return (c == ADD || c == SUBTRACT || c == MULTIPLY || c == DIVIDE || c == POW); } // 判断是否是数字或点(小数点),是则返回true private static boolean isDigitOrPoint(char c) { return (Character.isDigit(c) || c == '.'); } /* 比较两个运算符的优先级, * operator1等于operator2则返回0 * operator1大于operator2则返回大于0的数, * operator1小于operator2则返回小于0的数 */ private static int compareOperatorPriority(char operator1, char operator2) { // , ( + - * / ^ ) int[] operatorPriority = {0, 1, 2, 2, 3, 3, 4, 5}; int index1 = 0, index2 = 0; switch (operator1) { case COMMA: index1 = 0; break; case LEFT_PARENTHESIS: index1 = 1; break; case ADD: index1 = 2; break; case SUBTRACT: index1 = 3; break; case MULTIPLY: index1 = 4; break; case DIVIDE: index1 = 5; break; case POW: index1 = 6; break; case RIGHT_PARENTHESIS: index1 = 7; break; } switch (operator2) { case COMMA: index2 = 0; break; case LEFT_PARENTHESIS: index2 = 1; break; case ADD: index2 = 2; break; case SUBTRACT: index2 = 3; break; case MULTIPLY: index2 = 4; break; case DIVIDE: index2 = 5; break; case POW: index2 = 6; break; case RIGHT_PARENTHESIS: index2 = 7; break; } return operatorPriority[index1] - operatorPriority[index2]; } // 双目运算 private static String calculate(String n1, String n2, char operator) { BigDecimal bD1 = new BigDecimal(n1); BigDecimal bD2 = new BigDecimal(n2); switch (operator) { case ADD: return bD1.add(bD2).toString(); case SUBTRACT: return bD1.subtract(bD2).toString(); case MULTIPLY: return bD1.multiply(bD2).toString(); case DIVIDE: try { return bD1.divide(bD2).toString(); } catch (Exception ex) { return bD1.divide(bD2, 100, BigDecimal.ROUND_HALF_UP).toString(); } default: return "0"; } } // 单目运算 private static String calculate(String n, char operator) { BigDecimal bd = new BigDecimal(n); switch (operator) { case FACTORIAL: BigDecimal tempResult = BigDecimal.ONE; for (int i = 2, length = bd.intValue(); i <= length; i++) { tempResult = tempResult.multiply(new BigDecimal(String.valueOf(i))); } return tempResult.toString(); case POW2: return bd.multiply(bd).toString(); case POW3: return bd.multiply(bd).multiply(bd).toString(); case MINUS: return bd.multiply(new BigDecimal("-1")).toString(); case SIN: return String.valueOf(Math.sin(bd.doubleValue())); case COS: return String.valueOf(Math.cos(bd.doubleValue())); case TAN: return String.valueOf(Math.tan(bd.doubleValue())); case SQRT: return String.valueOf(Math.sqrt(bd.doubleValue())); case LN: return String.valueOf(Math.log(bd.doubleValue())); case LOG: return String.valueOf(Math.log10(bd.doubleValue())); default: return "0"; } }}
0 0
- 包含简单科学运算的表达式求值
- [计蒜客 15504 百度的科学计算器(简单)]表达式求值
- 简单的表达式求值
- 后缀表达式的运算求值
- 用C++实现中缀表达式求值即简单科学计算器的功能
- 百度的科学计算器(简单) Python 库函数实现表达式求值
- 实现简单的表达式求值
- 最简单的表达式求值
- 简单表达式求值的C++代码(10以内不包含括号的加减乘除)
- 栈的应用-后缀表达式运算求值
- 表达式求值运算规则
- 一种字符串表达式求值的简单方法
- 简单算术表达式的求值程序
- 栈的应用_简单表达式求值
- 简单表达式求值
- 简单表达式求值
- 简单算数表达式求值
- 简单算术表达式求值
- stirng与json进行数据格式转换的时候需要的jar包
- 极客班
- Ubuntu 部署 solr6.3.0 环境jdk1.8 tomcat9
- Ubuntu nginx 502 bad getaway
- C++使用第三方library
- 包含简单科学运算的表达式求值
- <context-param>与<init-param>的区别与作用
- js之类型转换与引用类型(Boolean/Number/String)
- Linux下MySQL默认安装目录和常用命令
- Notepad 格式化JS
- 【synchronized关键词】高并发下地单例模式
- leetcode 416 c++. Partition Equal Subset Sum
- 怎样创建FTP服务器
- 日常记录之BeanPostProcessor