重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
import java.util.Scanner;
成都创新互联专注为客户提供全方位的互联网综合服务,包含不限于网站制作、成都做网站、阿拉山口网络推广、微信平台小程序开发、阿拉山口网络营销、阿拉山口企业策划、阿拉山口品牌公关、搜索引擎seo、人物专访、企业宣传片、企业代运营等,从售前售中售后,我们都将竭诚为您服务,您的肯定,是我们最大的嘉奖;成都创新互联为所有大学生创业者提供阿拉山口建站搭建服务,24小时服务热线:18980820575,官方网址:www.cdcxhl.com
import java.util.Stack;
public class 表达式计算 {
private static StackString num = new StackString();//存后缀表达式
private static StackString sign = new StackString();//存入符号
private static StackInteger result = new StackInteger();//放结果
public static void getGroup(String line){//讲字符串转换为后缀表达式
for(int i=0; iline.length(); i++){
char c = line.charAt(i);
if((int)c=48 (int)c=57){//当遇到数字的时候,判断是不是多位数,然后在push进num
int j = i+1;
while(jline.length() (line.charAt(j)=48 line.charAt(j)=57)){
j++;
}
num.push(line.substring(i, j));
i = j-1;
}else if(c == '('){//遇到左括号直接存进num
sign.push(String.valueOf(c));
}else if(c == ')'){//遇到右括号从sign中pop栈顶元素push到num知道遇到'(',然后再pop掉'('
while(!sign.peek().equals("(")){
num.push(sign.pop());
}
sign.pop();
}else{
int n = 0;
if(!sign.empty()){//如果sign中没有元素,直接令n = 0
n = getNum(sign.peek().charAt(0));
}
int m = getNum(c);
if(m = n){//如果当前元素的运算级别比栈顶元素运算级别要高,就直接push进sign
sign.push(String.valueOf(c));
}else{
while(m n){//如果当前运算运算级别比sign栈顶元素运算级别要低,就将sign栈顶元素pop并且push进num,知道不符合条件
num.push(sign.pop());//输入例子2*3+6/3的时候,这里一直报错
if(!sign.empty()){
n = getNum(sign.peek().charAt(0));
}else{
n = 0;
}
}
sign.push(String.valueOf(c));
}
}
}
while(!sign.empty()){
num.push(sign.pop());
}
}
private static int getNum(char c){
int n = 0;
switch(c){
case '+':
case '-':
n = 1;
break;
case '*':
case '/':
n = 2;
break;
}
return n;
}
import java.util.Collections;
import java.util.Stack;
public class Calculator {
private StackString postfixStack = new StackString();//后缀式栈
private StackCharacter opStack = new StackCharacter();//运算符栈
private int [] operatPriority = new int[] {0,3,2,1,-1,1,0,2};//运用运算符ASCII码-40做索引的运算符优先级
public static void main(String[] args) {
System.out.println(5+12*(3+5)/7.0);
Calculator cal = new Calculator();
String s = "5+12*(3+5)/7";
double result = cal.calculate(s);
System.out.println(result);
}
/**
* 按照给定的表达式计算
* @param expression 要计算的表达式例如:5+12*(3+5)/7
* @return
*/
public double calculate(String expression) {
StackString resultStack = new StackString();
prepare(expression);
Collections.reverse(postfixStack);//将后缀式栈反转
String firstValue ,secondValue,currentValue;//参与计算的第一个值,第二个值和算术运算符
while(!postfixStack.isEmpty()) {
currentValue = postfixStack.pop();
if(!isOperator(currentValue.charAt(0))) {//如果不是运算符则存入操作数栈中
resultStack.push(currentValue);
} else {//如果是运算符则从操作数栈中取两个值和该数值一起参与运算
secondValue = resultStack.pop();
firstValue = resultStack.pop();
String tempResult = calculate(firstValue, secondValue, currentValue.charAt(0));
resultStack.push(tempResult);
}
}
return Double.valueOf(resultStack.pop());
}
/**
* 数据准备阶段将表达式转换成为后缀式栈
* @param expression
*/
private void prepare(String expression) {
opStack.push(',');//运算符放入栈底元素逗号,此符号优先级最低
char[] arr = expression.toCharArray();
int currentIndex = 0;//当前字符的位置
int count = 0;//上次算术运算符到本次算术运算符的字符的长度便于或者之间的数值
char currentOp ,peekOp;//当前操作符和栈顶操作符
for(int i=0;iarr.length;i++) {
currentOp = arr[i];
if(isOperator(currentOp)) {//如果当前字符是运算符
if(count 0) {
postfixStack.push(new String(arr,currentIndex,count));//取两个运算符之间的数字
}
peekOp = opStack.peek();
if(currentOp == ')') {//遇到反括号则将运算符栈中的元素移除到后缀式栈中直到遇到左括号
while(opStack.peek() != '(') {
postfixStack.push(String.valueOf(opStack.pop()));
}
opStack.pop();
} else {
while(currentOp != '(' peekOp != ',' compare(currentOp,peekOp) ) {
postfixStack.push(String.valueOf(opStack.pop()));
peekOp = opStack.peek();
}
opStack.push(currentOp);
}
count = 0;
currentIndex = i+1;
} else {
count++;
}
}
if(count 1 || (count == 1 !isOperator(arr[currentIndex]))) {//最后一个字符不是括号或者其他运算符的则加入后缀式栈中
postfixStack.push(new String(arr,currentIndex,count));
}
while(opStack.peek() != ',') {
postfixStack.push(String.valueOf( opStack.pop()));//将操作符栈中的剩余的元素添加到后缀式栈中
}
}
/**
* 判断是否为算术符号
* @param c
* @return
*/
private boolean isOperator(char c) {
return c == '+' || c == '-' || c == '*' || c == '/' || c == '(' ||c == ')';
}
/**
* 利用ASCII码-40做下标去算术符号优先级
* @param cur
* @param peek
* @return
*/
public boolean compare(char cur,char peek) {// 如果是peek优先级高于cur,返回true,默认都是peek优先级要低
boolean result = false;
if(operatPriority[(peek)-40] = operatPriority[(cur) - 40]) {
result = true;
}
return result;
}
/**
* 按照给定的算术运算符做计算
* @param firstValue
* @param secondValue
* @param currentOp
* @return
*/
private String calculate(String firstValue,String secondValue,char currentOp) {
String result = "";
switch(currentOp) {
case '+':
result = String.valueOf(ArithHelper.add(firstValue, secondValue));
break;
case '-':
result = String.valueOf(ArithHelper.sub(firstValue, secondValue));
break;
case '*':
result = String.valueOf(ArithHelper.mul(firstValue, secondValue));
break;
case '/':
result = String.valueOf(ArithHelper.div(firstValue, secondValue));
break;
}
return result;
}
}
public class ArithHelper {
// 默认除法运算精度
private static final int DEF_DIV_SCALE = 16;
// 这个类不能实例化
private ArithHelper() {
}
/**
* 提供精确的加法运算。
*
* @param v1 被加数
* @param v2 加数
* @return 两个参数的和
*/
public static double add(double v1, double v2) {
java.math.BigDecimal b1 = new java.math.BigDecimal(Double.toString(v1));
java.math.BigDecimal b2 = new java.math.BigDecimal(Double.toString(v2));
return b1.add(b2).doubleValue();
}
public static double add(String v1, String v2) {
java.math.BigDecimal b1 = new java.math.BigDecimal(v1);
java.math.BigDecimal b2 = new java.math.BigDecimal(v2);
return b1.add(b2).doubleValue();
}
/**
* 提供精确的减法运算。
*
* @param v1 被减数
* @param v2 减数
* @return 两个参数的差
*/
public static double sub(double v1, double v2) {
java.math.BigDecimal b1 = new java.math.BigDecimal(Double.toString(v1));
java.math.BigDecimal b2 = new java.math.BigDecimal(Double.toString(v2));
return b1.subtract(b2).doubleValue();
}
public static double sub(String v1, String v2) {
java.math.BigDecimal b1 = new java.math.BigDecimal(v1);
java.math.BigDecimal b2 = new java.math.BigDecimal(v2);
return b1.subtract(b2).doubleValue();
}
/**
* 提供精确的乘法运算。
*
* @param v1
* 被乘数
* @param v2
* 乘数
* @return 两个参数的积
*/
public static double mul(double v1, double v2) {
java.math.BigDecimal b1 = new java.math.BigDecimal(Double.toString(v1));
java.math.BigDecimal b2 = new java.math.BigDecimal(Double.toString(v2));
return b1.multiply(b2).doubleValue();
}
public static double mul(String v1, String v2) {
java.math.BigDecimal b1 = new java.math.BigDecimal(v1);
java.math.BigDecimal b2 = new java.math.BigDecimal(v2);
return b1.multiply(b2).doubleValue();
}
/**
* 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 小数点以后10位,以后的数字四舍五入。
*
* @param v1
* 被除数
* @param v2
* 除数
* @return 两个参数的商
*/
public static double div(double v1, double v2) {
return div(v1, v2, DEF_DIV_SCALE);
}
public static double div(String v1, String v2) {
java.math.BigDecimal b1 = new java.math.BigDecimal(v1);
java.math.BigDecimal b2 = new java.math.BigDecimal(v2);
return b1.divide(b2, DEF_DIV_SCALE, java.math.BigDecimal.ROUND_HALF_UP).doubleValue();
}
/**
* 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指 定精度,以后的数字四舍五入。
*
* @param v1 被除数
* @param v2 除数
* @param scale 表示表示需要精确到小数点以后几位。
* @return 两个参数的商
*/
public static double div(double v1, double v2, int scale) {
if (scale 0) {
throw new IllegalArgumentException("The scale must be a positive integer or zero");
}
java.math.BigDecimal b1 = new java.math.BigDecimal(Double.toString(v1));
java.math.BigDecimal b2 = new java.math.BigDecimal(Double.toString(v2));
return b1.divide(b2, scale, java.math.BigDecimal.ROUND_HALF_UP).doubleValue();
}
/**
* 提供精确的小数位四舍五入处理。
*
* @param v 需要四舍五入的数字
* @param scale 小数点后保留几位
* @return 四舍五入后的结果
*/
public static double round(double v, int scale) {
if (scale 0) {
throw new IllegalArgumentException("The scale must be a positive integer or zero");
}
java.math.BigDecimal b = new java.math.BigDecimal(Double.toString(v));
java.math.BigDecimal one = new java.math.BigDecimal("1");
return b.divide(one, scale, java.math.BigDecimal.ROUND_HALF_UP).doubleValue();
}
public static double round(String v, int scale) {
if (scale 0) {
throw new IllegalArgumentException("The scale must be a positive integer or zero");
}
java.math.BigDecimal b = new java.math.BigDecimal(v);
java.math.BigDecimal one = new java.math.BigDecimal("1");
return b.divide(one, scale, java.math.BigDecimal.ROUND_HALF_UP).doubleValue();
}
}
Java 有一个jar包 叫 groovy
groovy可以实现动态执行 String格式的算数表达式
public static void main(String[] args) throws Exception{
String str1 = "1 + 2 * 3"; //表达式1 固定表达式
GroovyShell groovyShell = new GroovyShell();
Object value = groovyShell.evaluate(str1);
System.out.println(value);
String str2 = "A + B * C"; //表达式2 动态表达式
Binding binding = new Binding();
binding.setVariable("A",1); //表达式中 所有的A替换为1
binding.setVariable("B",2);//表达式中 所有的B替换为2
binding.setVariable("C",3);//表达式中 所有的C替换为3
GroovyShell groovyShell2 = new GroovyShell(binding);
Object value2 = groovyShell2.evaluate(str2); //str2 实际表达式为 1 + 2 * 3
System.out.println(value2);
}
1. 定义优先级和优先级表
Java代码
/**
* 运算符优先权
*/
public enum Precede {
/**
* 优先权高
*/
LARGER,
/**
* 优先权低
*/
LESS;
/**
* 优先级表
* + - * /
* +
* -
* *
* /
*/
private static Precede[][] precedes = new Precede[4][4];
static {
// 根据优先级表初始化precedes数组
for (int i = 0; i precedes.length; i++) {
for (int j = 0; j precedes[i].length; j++) {
if ((i == 0 || i == 1) j 1) {
precedes[i][j] = LESS;
} else {
precedes[i][j] = LARGER;
}
}
}
}
/**
* 判断2个运算符的优先级
*/
public static Precede judgePrecede(char operand1, char operand2) {
int left = getIndex(operand1);
int right = getIndex(operand2);
return precedes[left][right];
}
/**
* 获取运算符对应的数组索引
*/
private static int getIndex(char operand) {
switch (operand) {
case '+':
return 0;
case '-':
return 1;
case '*':
return 2;
case '/':
return 3;
default:
throw new IllegalArgumentException();
}
}
}
2. 表达式求值
Java代码
/**
* 整数表达式运算
*/
public class EvaluateExpression {
/**
* 表达式
*/
private String expression;
/**
* 最初的表达式
*/
private String initExpression;
/**
* 运算符栈
*/
private MyStackCharacter optr = new MyArrayStackCharacter();
/**
* 操作数栈
*/
private MyStackInteger opnd = new MyArrayStackInteger();
/**
* 表明下一个是否应该是数字
*/
private boolean numberNext;
public EvaluateExpression(String expression) {
this.expression = expression;
this.initExpression = expression;
numberNext = true;
}
/**
* 求值
*/
public Integer evaluate() {
delBlank();
handleParentheses();
while (true) {
if ("".equals(expression)) {
break;
}
if (expression.matches("^-?\\d+.*$") numberNext) {
opnd.push(getInteger());
continue;
} else {
Character operand = expression.charAt(0);
numberNext = true;
expression = expression.substring(1);
Character pop = optr.pop();
if (pop == null) {
optr.push(operand);
continue;
} else {
Precede precede = Precede.judgePrecede(pop, operand);
switch (precede) {
// 优先级高时运算前2个操作数
case LARGER: {
optr.push(operand);
Integer next = opnd.pop();
Integer last = opnd.pop();
evaluateNow(last, pop, next);
break;
}
// 优先级低时运算前一个操作数和后一个操作数
case LESS: {
optr.push(pop);
Integer last = opnd.pop();
Integer next = getInteger();
evaluateNow(last, operand, next);
break;
}
}
}
}
}
// 运算结果
Integer result = null;
if (optr.length() == 0 opnd.length() == 1) {
result = opnd.pop();
} else if (optr.length() == 1 opnd.length() == 2) {
Integer next = opnd.pop();
Integer last = opnd.pop();
evaluateNow(last, optr.pop(), next);
result = opnd.pop();
} else {
throw new RuntimeException();
}
return result;
}
/**
* 进行实际的运算,并将结果入栈
*/
private void evaluateNow(Integer last, Character operand, Integer next) {
switch (operand) {
case '+':
opnd.push(last + next);
break;
case '-':
opnd.push(last - next);
break;
case '*':
opnd.push(last * next);
break;
case '/':
opnd.push(last / next);
break;
}
}
/**
* 获得表达式开头部分的整数
*/
private Integer getInteger() {
StringBuilder sb = new StringBuilder();
int count = 0; // 整数位
boolean lessZero = false; // 是否是负数
if (expression.startsWith("-")) {
sb.append("-");
count++;
lessZero = true;
}
int i = (lessZero ? 1 : 0);
for (; i expression.length(); i++) {
char c = expression.charAt(i);
if (c = '0' c = '9') {
sb.append(c);
count++;
} else {
break;
}
}
expression = expression.substring(count);
numberNext = false;
return Integer.valueOf(sb.toString());
}
/**
* 处理括号. 将括号内的字符串作为子表达式计算.
*/
private void handleParentheses() {
while (expression.contains("(")) {
// 左括号的索引
int left = 0;
// 右括号的索引
int right = 0;
// 左括号的数量
int count = 0;
// 求出左括号索引
left = expression.indexOf('(');
// 求出对应的右括号索引
for (int i = left; i expression.length(); i++) {
char c = expression.charAt(i);
if (c == ')') {
count--;
// count为0时才是对应的右括号
if (count == 0) {
right = i;
break;
}
} else if (c == '(') {
count++;
} else {
continue;
}
}
// 左右括号之间是一个子表达式, 计算子表达式的值,并根据结果构造出新的表达式
EvaluateExpression evaluateExpression = new EvaluateExpression(expression.substring(left + 1, right));
expression = expression.substring(0, left) + evaluateExpression.evaluate()
+ expression.substring(right + 1);
}
}
/**
* 删除表达式中的空白字符
*/
private void delBlank() {
expression = expression.replaceAll("\\s", "");
}
@Override
public String toString() {
return initExpression;
}
}
3. 进行测试
Java代码
@Test
public void testEvaluate() {
EvaluateExpression expression = new EvaluateExpression("1 + 2 ");
System.out.println(expression + " = " + expression.evaluate());
expression = new EvaluateExpression("4 + 2 * 3 - 10 / 5");
System.out.println(expression + " = " + expression.evaluate());
expression = new EvaluateExpression("(1+2) * (4 + 5) - (9 / 7)");
System.out.println(expression + " = " + expression.evaluate());
expression = new EvaluateExpression("(1 + (3 * (4 - 9)))");
System.out.println(expression + " = " + expression.evaluate());
expression = new EvaluateExpression("(1 + (3 * (4 - 9))) + (3 * (2 + 3))");
System.out.println(expression + " = " + expression.evaluate());
}
测试的结果为:
1 + 2 = 3
4 + 2 * 3 - 10 / 5 = 8
(1+2) * (4 + 5) - (9 / 7) = 26
(1 + (3 * (4 - 9))) = -14
(1 + (3 * (4 - 9))) + (3 * (2 + 3)) = 1