问题描述:
输入一个计算表达式,计算该表达式的值。表达式复杂度分为两级:第一级:加减乘除;
第二级:包含sin、cos、tgn、sqrt、exp、pow函数
*解决思路
1.设置两个栈,一个用于存放操作数,一个用于存放运算符
private static Stack<Double> vals = new Stack<Double>();
private static Stack<Character> ops = new Stack<Character>();
2.基于后缀表达式设计,从左往右遍历字符数组,遇到数字入栈,遇到’('以及一些特殊函数预算符入栈。这里sin用’s’代替入栈,cos用’c’代替……
if(i + 4 <= ch.length){
String str1 = new String(ch,i,3);
String str2 = new String(ch,i,4);
if(str1.equals("sin")) {
ops.push(ch[i]);//s表示sin
i+=3;
}else if(str1.equals("cos")){
ops.push(ch[i]);//c表示cos
i+=3;
}else if(str1.equals("tan") || str1.equals("tgn")){
ops.push(ch[i]);//t表示tan函数
i+=3;
}else if(str1.equals("exp")){
ops.push(ch[i]);//e表示指数函数
i+=3;
}else if(str2.equals("sqrt")){
ops.push('q');//q表示开方
i +=4;
}
}
3.若扫描到数字,则数字入栈(这里特别注意负数的处理,以及浮点数的处理)
if(ch[i] == '-' && (vals.empty() || ops.lastElement() == '(')){
isNegative = true;//判断是否为负数
i ++;
}
if ((ch[i] >= '0' && ch[i] <= '9') || ch[i] == '.') {
double val = 0;
double temp = 1;
boolean byPoint = false;
while ((ch[i] >= '0' && ch[i] <= '9') || ch[i] == '.') {
if (ch[i] == '.') {
i++;
byPoint = true;
temp = 10;
continue;
}
if (byPoint) {
int x = (int) ch[i] - 48;
val += ((double) x) / temp;
temp = temp * 10;
i++;
} else {
int x = (int) ch[i] - 48;
val = val*10 + x;
i++;
}
}
if(isNegative) val = -1*val;
vals.push(val);
continue;
}
4.扫描到运算符,则弹出栈里更高级或者同级的运算符,这里特别注意特殊函数的运算级别最高,而且遇见特殊函数只弹出一个操作数。
else if(ch[i] == '+' || ch[i] == '-' || ch[i] == '*'|| ch[i] == '/'||ch[i] == '^'){
char t = ch[i];
char c;
switch (t){
case '+':
case '-':
c = ops.pop();
while (c != '(' && c != '#'){
double r;
double l;
if(c == '+'){
r = vals.pop();
l = vals.pop();
vals.push(l + r);
}else if(c == '-'){
r = vals.pop();
l = vals.pop();
vals.push(l - r);
}else if(c == '*'){
r = vals.pop();
l = vals.pop();
vals.push(l*r);
}else if(c == '/'){
r = vals.pop();
l = vals.pop();
vals.push(l/r);
}else if(c == '^'){
r = vals.pop();
l = vals.pop();
vals.push(pow(l,r));
}else if(c == 'q'){
r = vals.pop();
vals.push(sqrt(r));
} else if (c == 's') {
r = vals.pop();
vals.push(sin(r));
}else if(c == 'c'){
r = vals.pop();
vals.push(cos(r));
}else if(c == 't'){
r = vals.pop();
vals.push(tan(r));
}else if(c == 'e'){
r = vals.pop();
vals.push(exp(r));
}
c = ops.pop();
}
ops.push(c);
ops.push(ch[i]);
i++;
break;
case '*':
case '/':
c = ops.pop();
while (c != '(' && c != '#' && c != '+' && c != '-'){
double r;
double l;
if(c == '*'){
r = vals.pop();
l = vals.pop();
vals.push(l*r);
}else if(c == '/'){
r = vals.pop();
l = vals.pop();
vals.push(l/r);
}else if(c == '^'){
r = vals.pop();
l = vals.pop();
vals.push(pow(l,r));
}else if(c == 'q'){
r = vals.pop();
vals.push(sqrt(r));
} else if (c == 's') {
r = vals.pop();
vals.push(sin(r));
}else if(c == 'c'){
r = vals.pop();
vals.push(cos(r));
}else if(c == 't'){
r = vals.pop();
vals.push(tan(r));
}else if(c == 'e'){
r = vals.pop();
vals.push(exp(r));
}
c = ops.pop();
}
ops.push(c);
ops.push(ch[i]);
i++;
break;
case '^':
ops.push('^');
i ++;
break;
}
continue;
}
遇到左括号直接入栈
else if(ch[i] == '('){
ops.push(ch[i]);
i ++;
continue;
}
遇到右括号,拼命弹出运算符和操作数,不停地算直到栈中遇到’#’(结束标志)或左括号
else if(ch[i] == ')' || ch[i] == '\0'){
char c = ops.pop();
while(c != '(' && c != '#'){
double r;
double l;
if(c == '+'){
r = vals.pop();
l = vals.pop();
vals.push(l + r);
}else if(c == '-'){
r = vals.pop();
l = vals.pop();
vals.push(l - r);
}else if(c == '*'){
r = vals.pop();
l = vals.pop();
vals.push(l*r);
}else if(c == '/'){
r = vals.pop();
l = vals.pop();
vals.push(l/r);
}else if(c == '^'){
r = vals.pop();
l = vals.pop();
vals.push(pow(l,r));
}else if(c == 'q'){
r = vals.pop();
vals.push(sqrt(r));
} else if (c == 's') {
r = vals.pop();
vals.push(sin(r));
}else if(c == 'c'){
r = vals.pop();
vals.push(cos(r));
}else if(c == 't'){
r = vals.pop();
vals.push(tan(r));
}else if(c == 'e'){
r = vals.pop();
vals.push(exp(r));
}
c = ops.pop();
}
i++;
continue;
完整代码:
package Homework;
import java.util.Scanner;
import java.util.Stack;
import static java.lang.Math.*;
public class calculator2 {
private static Stack<Double> vals = new Stack<Double>();
private static Stack<Character> ops = new Stack<Character>();
private static void calculate(String str){
char[] ch = (str+"\0").toCharArray();
ops.push('#');
int i = 0;
while(i < ch.length) {
boolean isNegative = false;
if(i + 4 <= ch.length){
String str1 = new String(ch,i,3);
String str2 = new String(ch,i,4);
if(str1.equals("sin")) {
ops.push(ch[i]);//s表示sin
i+=3;
}else if(str1.equals("cos")){
ops.push(ch[i]);//c表示cos
i+=3;
}else if(str1.equals("tan") || str1.equals("tgn")){
ops.push(ch[i]);//t表示tan函数
i+=3;
}else if(str1.equals("exp")){
ops.push(ch[i]);//e表示指数函数
i+=3;
}else if(str2.equals("sqrt")){
ops.push('q');//q表示开方
i +=4;
}
}
if(ch[i] == '-' && (vals.empty() || ops.lastElement() == '(')){
isNegative = true;
i ++;
}
if ((ch[i] >= '0' && ch[i] <= '9') || ch[i] == '.') {
double val = 0;
double temp = 1;
boolean byPoint = false;
while ((ch[i] >= '0' && ch[i] <= '9') || ch[i] == '.') {
if (ch[i] == '.') {
i++;
byPoint = true;
temp = 10;
continue;
}
if (byPoint) {
int x = (int) ch[i] - 48;
val += ((double) x) / temp;
temp = temp * 10;
i++;
} else {
int x = (int) ch[i] - 48;
val = val*10 + x;
i++;
}
}
if(isNegative) val = -1*val;
vals.push(val);
continue;
}else if(ch[i] == '+' || ch[i] == '-' || ch[i] == '*'|| ch[i] == '/'||ch[i] == '^'){
char t = ch[i];
char c;
switch (t){
case '+':
case '-':
c = ops.pop();
while (c != '(' && c != '#'){
double r;
double l;
if(c == '+'){
r = vals.pop();
l = vals.pop();
vals.push(l + r);
}else if(c == '-'){
r = vals.pop();
l = vals.pop();
vals.push(l - r);
}else if(c == '*'){
r = vals.pop();
l = vals.pop();
vals.push(l*r);
}else if(c == '/'){
r = vals.pop();
l = vals.pop();
vals.push(l/r);
}else if(c == '^'){
r = vals.pop();
l = vals.pop();
vals.push(pow(l,r));
}else if(c == 'q'){
r = vals.pop();
vals.push(sqrt(r));
} else if (c == 's') {
r = vals.pop();
vals.push(sin(r));
}else if(c == 'c'){
r = vals.pop();
vals.push(cos(r));
}else if(c == 't'){
r = vals.pop();
vals.push(tan(r));
}else if(c == 'e'){
r = vals.pop();
vals.push(exp(r));
}
c = ops.pop();
}
ops.push(c);
ops.push(ch[i]);
i++;
break;
case '*':
case '/':
c = ops.pop();
while (c != '(' && c != '#' && c != '+' && c != '-'){
double r;
double l;
if(c == '*'){
r = vals.pop();
l = vals.pop();
vals.push(l*r);
}else if(c == '/'){
r = vals.pop();
l = vals.pop();
vals.push(l/r);
}else if(c == '^'){
r = vals.pop();
l = vals.pop();
vals.push(pow(l,r));
}else if(c == 'q'){
r = vals.pop();
vals.push(sqrt(r));
} else if (c == 's') {
r = vals.pop();
vals.push(sin(r));
}else if(c == 'c'){
r = vals.pop();
vals.push(cos(r));
}else if(c == 't'){
r = vals.pop();
vals.push(tan(r));
}else if(c == 'e'){
r = vals.pop();
vals.push(exp(r));
}
c = ops.pop();
}
ops.push(c);
ops.push(ch[i]);
i++;
break;
case '^':
ops.push('^');
i ++;
break;
}
continue;
}else if(ch[i] == '('){
ops.push(ch[i]);
i ++;
continue;
}else if(ch[i] == ')' || ch[i] == '\0'){
char c = ops.pop();
while(c != '(' && c != '#'){
double r;
double l;
if(c == '+'){
r = vals.pop();
l = vals.pop();
vals.push(l + r);
}else if(c == '-'){
r = vals.pop();
l = vals.pop();
vals.push(l - r);
}else if(c == '*'){
r = vals.pop();
l = vals.pop();
vals.push(l*r);
}else if(c == '/'){
r = vals.pop();
l = vals.pop();
vals.push(l/r);
}else if(c == '^'){
r = vals.pop();
l = vals.pop();
vals.push(pow(l,r));
}else if(c == 'q'){
r = vals.pop();
vals.push(sqrt(r));
} else if (c == 's') {
r = vals.pop();
vals.push(sin(r));
}else if(c == 'c'){
r = vals.pop();
vals.push(cos(r));
}else if(c == 't'){
r = vals.pop();
vals.push(tan(r));
}else if(c == 'e'){
r = vals.pop();
vals.push(exp(r));
}
c = ops.pop();
}
i++;
continue;
}else{
System.out.println("输入异常!");
break;
}
}
System.out.println(vals.pop());
}
public static void main(String[] args) {
while (true){
Scanner scanner = new Scanner(System.in);
System.out.println("请输入算数表达式:");
String str = scanner.next();
if(str.equals("#")){
break;
}
try{
calculate(str);
}catch (Exception e){
System.out.println("输入异常!");
}
}
}
}
运行示范:
请输入算数表达式:
sin3.14
0.0015926529164868282
请输入算数表达式:
exp(1)*2+(-3)
2.43656365691809
请输入算数表达式:
#
Process finished with exit code 0