1. 程式人生 > >表示式求值(逆波蘭式)

表示式求值(逆波蘭式)

表示式求值

時間限制:3000 ms  |  記憶體限制:65535 KB 難度:4
描述
ACM隊的mdd想做一個計算器,但是,他要做的不僅僅是一計算一個A+B的計算器,他想實現隨便輸入一個表示式都能求出它的值的計算器,現在請你幫助他來實現這個計算器吧。
比如輸入:“1+2/4=”,程式就輸出1.50(結果保留兩位小數)
輸入
第一行輸入一個整數n,共有n組測試資料(n<10)。
每組測試資料只有一行,是一個長度不超過1000的字串,表示這個運算式,每個運算式都是以“=”結束。這個表示式裡只包含+-*/與小括號這幾種符號。其中小括號可以巢狀使用。資料保證輸入的運算元中不會出現負數。
資料保證除數不會為0
輸出
每組都輸出該組運算式的運算結果,輸出結果保留兩位小數。
樣例輸入
2
1.000+2/4=
((1+2)*5+1)/4=
樣例輸出
1.50
4.00
/*
*    這裡主要是逆波蘭式的實現,使用兩個stack 這裡用字串來模擬一個stack,第一步,將中綴表示式轉變為字尾表示式
*    第二步,然後再使用一個stack,計算字尾表示式的結果,這一步很容易出錯,考慮到浮點數的問題。
*/
#include <iostream>
#include <string>
#include <stack>
#include <iomanip>

using namespace std;

int cmp(char ch)     // 運算子優先順序 
{
	switch(ch)
	{
		case '+':
		case '-': return 1;
		case '*':
		case '/': return 2;
		default : return 0;
	}
}
void change(string &s1, string &s2)       // 中綴表示式轉變字尾表示式 
{
	stack <char > s;
	s.push('#');
	int i = 0;
	while(i < s1.length()-1)
	{
		if(s1[i] == '(')
		{
			s.push(s1[i++]);
		}
		else if(s1[i] == ')')
		{
			while(s.top() != '(')
			{
				s2 += s.top();
				s2 += ' ';
				s.pop();
			}
			s.pop();
			i++;
		}
		else if(s1[i] == '+'||s1[i] == '-'||s1[i] == '*'||s1[i] == '/')
		{
			while(cmp(s.top()) >= cmp(s1[i]))
			{
				s2 += s.top();
				s2 += ' ';
				s.pop();
			}
			s.push(s1[i]);
			i++;
		}
		else
		{
			while('0' <= s1[i]&&s1[i] <= '9'||s1[i] == '.')
			{
				s2 += s1[i++];
			}
			s2 += ' ';
		}
	}
	while(s.top() != '#')
	{
		s2 += s.top();
		s2 += ' ';
		s.pop();
	}
}

double value(string s2)         // 計算字尾表示式,得到其結果。 
{
	stack < double> s;
	double x,y;
	int i = 0;
	while(i < s2.length())
	{
		if(s2[i] == ' ')
		{
			i++;
			continue;
		}
		switch(s2[i])
		{
			case '+': x = s.top(); s.pop(); x += s.top(); s.pop(); i++; break;
			case '-': x = s.top(); s.pop(); x =s.top()-x; s.pop(); i++; break;
			case '*': x = s.top(); s.pop(); x *= s.top(); s.pop(); i++; break;
			case '/': x = s.top(); s.pop(); x = s.top()/x; s.pop(); i++; break;
			default :
			{
				x = 0;
				while('0' <= s2[i]&&s2[i] <= '9')
				{
					x = x*10+s2[i] - '0';
					i++;
				}
				if(s2[i] == '.')
				{
					double k = 10.0;
					y = 0;
					i++;
					while('0' <= s2[i]&&s2[i] <= '9')
					{
						y += ((s2[i]-'0')/k);
						i++;
						k *= 10;
					}
					x += y;
				}
			}
		}
		s.push(x);
	}
	return s.top();
}
int main(int argc, char const *argv[])
{
	int n;
	string s1,s2;
	cin>>n;
	while(n--)
	{
		cin>>s1;
		s2 = "";
		change(s1,s2);
		cout<<fixed<<setprecision(2)<<value(s2)<<endl;
	}
	return 0;
}