表达式计算

题目

输入一个表达式,计算出它的值。运算符有 + - × / ( )。

思路

这是我们学栈时碰到的一个问题,大体方法是利用双栈把中缀表达式转换成后缀表达式进行计算

------------------------------------------------------------------------------------------------

1.拆分数字与运算符

:遇到运算符截断、存储、清空。

2.转后缀表达式

:栈A存放后缀表达式,栈B存放运算符
记 B栈顶运算符为a1,当前运算符为a2(若a2为数字直接 a2->A )
1)若 a1>a2,a1->A,a2->B
1)若 a1<a2,a2->B;
2)若 a1>=a2
1.若a1>a2,a1->A;(只要该条件满足则一直执行,使得优先级高的运算符放在A中)
2.将高级运算符都赶走后,要判断a1=a2 ?( 即是否为()相遇)
如果为左右括号的话就把做括号弹出,否则把a2->B。(注意与1的区别,一个)可以一直赶走比它高级的运算法,但是只能抵消一个左括号)
PS: a1>a2 表示 在此式中先算a1再算a2,a1与a2的关系在初始化中建立。

3.计算后缀表达式

: 从左往右扫描,遇到运算符则处理前两位数字
-------------------------------------------------------------------------------------------------

代码

#include <iostream>
#include <queue>
#include <stack>
#include <string>
#include <cstdio>
#include <cstdlib>
using namespace std;
string ss;
vector<double> ans;
vector<string> s,A;
stack<char> B;
int cmp[8][8]={	{1,1,-1,-1,-1,1},
				{1,1,-1,-1,-1,1},
				{1,1,1,1,-1,1},
				{1,1,1,1,-1,1},
				{-1,-1,-1,-1,-1,0},
				{1,1,1,1,0,0}};
int gec[333];
bool isNum(char a){
	switch(a){
			case '+':
			case '-':
			case '*':
			case '/':
			case '(':
			case ')':
				return false;
	}
	return true;
}
void init(){
	gec['+']=0;
	gec['-']=1;
	gec['*']=2;
	gec['/']=3;
	gec['(']=4;
	gec[')']=5;
}
void Quit(int v){
	cout << "ERROR : ";
	switch(v){
		case 1:
			cout << "DIVISION BY 0";
			break;
		case 2:
			cout << "PARENTHESES ARE NOT EVEN";
			break;
	}
	cout << endl;
	exit(0);
}
double gen(string s){
	double tmp;
	sscanf(s.c_str(),"%lf",&tmp);
	return tmp;
}
void check(){
	stack<char> q;
	for (string::size_type i(0);i!=ss.size();i++){
		if (ss[i]=='(') q.push(ss[i]);
		if (ss[i]==')') {
			if (q.empty()) Quit(2);
			if (q.top()=='(') q.push(ss[i]);
			else q.pop();
		}
	}
	if (q.size()) Quit(2);
}
void ready(){
	cin >> ss;
	check();
	ss+=')';
	string str="";
	for (string::size_type i(0);i!=ss.size();i++){
		if (isNum(ss[i])){
			str+=ss[i];
		}else {
			if (str.size()) s.push_back(str);
			str=ss[i];
			s.push_back(str);
			str="";
		}
	}
}
void changetype(){
	B.push('(');
	for (unsigned int i(0);i!=s.size();i++){
		if (isNum(s[i][0])){
			A.push_back(s[i]);
		}else{
			char ch=s[i][0];
			if (cmp[gec[B.top()]][gec[ch]]<0){
				B.push(ch);
			}else 
			if (cmp[gec[B.top()]][gec[ch]]>=0){
				string str;
				while (cmp[gec[B.top()]][gec[ch]]>0){
                    str=B.top();
                    A.push_back(str);
                    B.pop();
                }
                if (cmp[gec[B.top()]][gec[ch]]==0){
					B.pop();
				}else{
					B.push(ch);
				}
			}
			
		}
	}
}
void calcit(){
	for (int i(0);i!=A.size();i++){
		if (isNum(A[i][0])) {
			ans.push_back(gen(A[i]));
		}else{
			double a1=ans[ans.size()-2];
			double a2=ans[ans.size()-1];
			printf("%.2f%c%.2f=",a1,A[i][0],a2);
			switch (A[i][0]){
				case '+':
					a1+=a2;
					break;
				case '-':
					a1-=a2;
					break;
				case '*':
					a1*=a2;
					break;
				case '/':
					if (!a2){
						Quit(1);
					}
					a1/=a2;
					break;
			}
			printf("%.2f\n",a1);
			ans.pop_back();
			ans[ans.size()-1]=a1;
		}
	}
	printf("%.3f\n",ans[0]);
}
int main(){
	init();
	ready();
	changetype();
	calcit();
	return 0;
}


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
因各个项目中需要使用根据字符串计算数值,这里写出一个算法,专门计算字符串。配有大量常用公式。只有一个人方法,直接调用即可。 类名:CustomMath 函数名:Calculations(string value) 说明:求解算式表达式字符串的值 表达式中包含的符号或函数: truncate, ceiling,floor,round,log10, sign,sinh,sqrt, asin,atan,cosh, tanh, sin,cos,tan ,abs,acos, exp,log,max,min,pow,mod,+,-,*,/,',',(,) 函数说明:(不区分大小写) truncate(num) 计算指定数的整数部分 truncate(1.23)=1 ceiling (num) 返回大于或等于指定的双精度浮点数的最小整数值 ceiling(1.23)=2 floor(num) 返回小于或等于指定双精度浮点数的最大整数 floor(1.23)=1 round(num) 将双精度浮点值舍入为最接近的整数值 round(1.23)=1 round(num,num1) 将小数值按指定的小数位数舍入 round(1.23,1)=1.2 log10(num) 返回指定数字以 10 为底的对数 log10(10)=1 sign(num) 返回表示数字符号的值 sign(1.23)=1 sinh(num) 返回指定角度的双曲正弦值 sinh(1.23)=1.5644 sqrt(num) 返回指定数字的平方根 sqrt(9)=3 sqrt(num,num1) 返回指定数字的num1根 sqrt(27,3)=3 asin(num) 返回正弦值为指定数字的角度 asin(0.5)=PI/6 atan(num) 返回正切值为指定数字的角度 atan(1)=45 cosh(num) 返回指定角度的双曲余弦值 cosh(1.23)=1.8567 tanh(num) 返回指定角度的双曲正切值 tanh(1.23)=0.8425 sin(num) 返回指定角度的正弦值 sin(PI/6)=0.5 cos(num) 返回指定角度的余弦值 sin(PI/3)=0.5 tan(num) 返回指定角度的余切值 sin(PI/4)=1 abs(num) 返回数字的绝对值 abs(-12)=12 acos(num) 返回余弦值为指定数字的角度 acos(0.5)=PI/3 exp(num) 返回 e 的指定次幂 exp(1)=2.718 log(num) 返回指定数字的自然对数(底为 e) log(e)=1 log(num,num1) 返回指定数字在使用指定底时的对数 log(e,e)=1 max(num,um1) 返回最大值 max(1,2)=2 min(num,num1) 返回最小值 min(1,2)=1 pow(num,num1) 返回指定数字的指定次幂 pow(2,2)=4 mod(num,num1) 返回余数 mod(3,2)=1 常量: PI 值:3.14159265358979323846 E 值:2.7182818284590452354 YEAR 值:当前年份 MONTH 值:当前月份 DAY 值: 当前日 HOUR 值:当前时 MINUTE 值:当前分 SECOND 值:当前秒 RANDOM 值:一个随机数(0-1 之间) 实例 系统计算:1+2*3/4-0.5=2 函数计算:1+2*3/4-0.5=2 调用方式:CustomMath.Calculations("1+2*3/4-0.5") 系统计算:(1+2)*3/4-0.5=1.75 函数计算:(1+2)*3/4-0.5=1.75 调用方式:CustomMath.Calculations("(1+2)*3/4-0.5") 系统计算:(sin(pi)+sqrt(3+5*7+(2+8/4*5+2)))/6=1.20185042515466 公式计算:(sin(pi)+sqrt(3+5*7+(2+8/4*5+2)))/6=1.20185042515466 调用方式:CustomMath.Calculations("(sin(pi)+sqrt(3+5*7+(2+8/4*5+2)))/6") 系统计算:sin(pow(3,2)/4)+3.5-9*sqrt(81)=-76.7219268031121 函数计算:sin(pow(3,2)/4)+3.5-9*sqrt(81)=-76.7219268031121 调用方式:CustomMath.Calculations("sin(pow(3,2)/4)+3.5-9*sqrt(81)")
Java表达式计算可以使用Java自带的表达式计算库,也可以手动实现表达式计算。 使用Java自带的表达式计算库可以通过以下步骤实现: 1. 引入Java自带的表达式计算库:`import javax.script.ScriptEngineManager;` 2. 创建ScriptEngine对象:`ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("JavaScript");` 3. 调用eval方法计算表达式:`Object result = engine.eval(expression);` 其中,expression为需要计算表达式,result为计算结果。 例如,计算表达式"1+2*3"的值,可以通过以下代码实现: ``` import javax.script.ScriptEngineManager; import javax.script.ScriptEngine; import javax.script.ScriptException; public class ExpressionCalculator { public static void main(String[] args) throws ScriptException { String expression = "1+2*3"; ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("JavaScript"); Object result = engine.eval(expression); System.out.println(result); } } ``` 输出结果为7。 手动实现表达式计算可以使用栈来实现。具体步骤如下: 1. 将表达式转换为后缀表达式(逆波兰表达式)。 2. 遍历后缀表达式,如果是数字,则入栈;如果是运算符,则从栈中弹出两个数进行运算,并将结果入栈。 3. 遍历完后缀表达式,栈中剩下的数就是表达式计算结果。 例如,计算表达式"1+2*3"的值,可以通过以下代码实现: ``` import java.util.Stack; public class ExpressionCalculator { public static void main(String[] args) { String expression = "1+2*3"; String[] postfix = toPostfix(expression); int result = calculate(postfix); System.out.println(result); } private static String[] toPostfix(String expression) { Stack<Character> stack = new Stack<>(); StringBuilder postfix = new StringBuilder(); for (int i = 0; i < expression.length(); i++) { char ch = expression.charAt(i); if (Character.isDigit(ch)) { postfix.append(ch); } else { while (!stack.isEmpty() && priority(stack.peek()) >= priority(ch)) { postfix.append(stack.pop()); } stack.push(ch); } } while (!stack.isEmpty()) { postfix.append(stack.pop()); } return postfix.toString().split(""); } private static int calculate(String[] postfix) { Stack<Integer> stack = new Stack<>(); for (String token : postfix) { if (Character.isDigit(token.charAt(0))) { stack.push(Integer.parseInt(token)); } else { int b = stack.pop(); int a = stack.pop(); int result = 0; switch (token) { case "+": result = a + b; break; case "-": result = a - b; break; case "*": result = a * b; break; case "/": result = a / b; break; } stack.push(result); } } return stack.pop(); } private static int priority(char ch) { switch (ch) { case '+': case '-': return 1; case '*': case '/': return 2; default: return 0; } } } ``` 输出结果为7。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值