主要有以下功能:可以连续计算四则运算,可以自己分辨多位数,小数,负数。
后续会加入sin(),cos()等。(已经加入sin,cos,tan,次方pow,阶乘!
,开平方sqrt,取对数log)
主要原理:
建立两个栈,一个用于存放数字,一个用于存放符号。
判断符号优先级,当符号优先级低于符号栈的栈头时,栈头出栈。(括号另算)否则则入栈。
出栈的符号进行运算,读取数字栈的两个数字并进行运算,将计算值返回至数字栈。
当输入的式子已全部读取完成时,若此时符号栈还有元素(此时数字栈肯定也还有),则从栈头逐个出栈,并进行运算。并将最后的计算值,返回数字栈的栈头。
对于括号,“(”拥有最高的优先级,“)”则为最低优先级。当运行时符号栈的出栈会在栈头为“(”时停止。
上面只是大致的概括,具体的请看程序:
#include<stack>
#include<iostream>
#include<math.h>
using namespace std;
stack<long double> _nu; //用于存储数字的栈
stack<char> op; //用于存储符号的栈
int nu_flag = 0; //用于判断是否为多位数
int de_flag = 0; //用于判断小数点
int ne_flag = 1; //用于判断负数
int tri_flag = 0; //用于判断三角函数
int judge_time = 0; //用于判断使用judge_time的次数
void nu_operat( char op ); //符号操作函数
char tri_function( char str ); //符号判断函数
long double fact( long double _number ); //阶乘运算函数
long double level( char str ) //用于判断优先级
{
if( str == '(')
return 6;
else if( str == '!' )
return 5.85;
else if( str == '^' )
return 5.75;
else if ( (str == 'g') || (str == 'r') )
return 5.73;
else if( (( str == 'n' ) && ((tri_flag == 3) || (op.top() == 'n'))) ||
(( str == 's' ) && ((tri_flag == 6) || (op.top() == 's'))) ||
(( str == 't' ) && ((tri_flag == 9) || (op.top() == 't'))) )
return 5.5; //拿这个做示例,当这个为6.5时,sin(1.57)
else if( ( str == '*' ) || ( str == '/' ) )
return 5;
else if( ( str == '+' ) || ( str == '-' ) )
return 4;
else if( ( str >= '0' ) || ( str <= '9' ) )
return 3;
else if( str == ')' )
return 2;
else if( str == '#' )
return 1;
else
return 0;
}
int judge(char str1)
{
long double num = 0;
char op1;
int flag = 0; //用于判断括号的清除
char str;
judge_time++;
str = tri_function( str1 );
if( (str == '-') || (str == '(') )ne_flag++;
if( (ne_flag == 2) && (str == '(') )ne_flag = 1;
if( ( str >= '0' ) && ( str <= '9') && ( nu_flag == 0 )) //此处为数字栈的入栈口一,为1位数入栈口
{
num = (long double)str -48;
if(ne_flag == 2) num = num*(-1); //进行负数的转换
else ne_flag =0;
_nu.push(num);
nu_flag = 1;
}else if( ( ( str >= '0' ) && ( str <= '9') || ( str == '.' ) ) && ( nu_flag == 1) ) //此处为数字栈的入栈扣二,多位数和小数的入栈口
{
if((!de_flag)&&(str != '.')) //此处为多位数的入栈口
{
num = 10 * _nu.top();
if(ne_flag != 2) num = num + (long double)str - 48;
else num = num - (long double)str + 48; //进行负数转换
_nu.pop();
_nu.push(num);
}else if(de_flag) //此处为小数的入栈口
{
num = _nu.top();
if(ne_flag != 2) num = num + ( (long double)str - 48 ) / pow(10,de_flag);
else num = num - ( (long double)str -48 ) / pow(10,de_flag); //进行负数转换
_nu.pop();
_nu.push(num);
}
if( (str == '.') || ( de_flag ) )de_flag ++;
nu_flag = 1;
}else if( ( ( level(str) == 4 ) || ( level(str) == 5 ) || ( level(str) == 5.75 ) || ( level(str) == 5.85 ) || ( level(str) == 6 ) ||
( (str == 'n') && (tri_flag == 3) ) || ( (str == 's') && (tri_flag == 6) ) || ( (str == 't') && (tri_flag ==9) ) ||
( (str == 'g') && (tri_flag == 12)) || ( (str == 'r') && (tri_flag == 16)) ) &&
( ( level( str ) > level( op.top() ) ) || ( ( op.top() == '(' ) && ( level(str) >= 4 ) ) ) )
{ //此处为符号栈的入栈口
if( (str != '(') && (str != '-' ) )ne_flag = 0;
if( (ne_flag != 2) || ((str == '-')&&(judge_time == 1)) )op.push( str ); //仅首个字符为'-'号时可进入
if((str == '-')&&(judge_time == 1)) ne_flag = 0;
nu_flag = 0;
de_flag = 0;
return num;
}else if( ( ( level(str) >= 4 ) && ( ( level( str ) <= level(( op.top() ) ) ) ) || ( str == ')') ) )
{ //此处为符号栈的出栈口一,即当仍有输入时的出栈规则
if( (str != '(') && (str != '-' ) )ne_flag = 0;
nu_flag = 0;
de_flag = 0;
char a = op.top();
while( ( ( level( str ) <= level( op.top() ) )&& ( op.top() != '#' ) ) && ( op.top() != '(' ) )
{
op1 = op.top();
op.pop();
nu_operat( op1 );
if( ( op.top() == '(' ) && ( str == ')' ) )
{
op.pop();
flag = 1;
break;
}
}
if( str != ')' )op.push( str );
else if( ( str == ')' ) && ( op.top() == '(' ) && ( flag == 0 ) )op.pop();
char b = op.top();
long double c = _nu.top();
return num;
}
while( (op.top() != '#') && ( str == 'z' ) ) //此处为符号栈的出栈口二,即没有输入时的出栈规则
{
op1 = op.top();
op.pop();
nu_operat( op1 );
}
return num;
}
void nu_operat( char op ) //符号运算,使相应的符号进行运算,并将结果存入数字栈头部
{
long double nu1,nu2;
switch(op)
{
case '*':
nu1 = _nu.top();
_nu.pop();
nu2 = _nu.top();
_nu.pop();
_nu.push( nu2 * nu1 );
break;
case '/':
nu1 = _nu.top();
_nu.pop();
nu2 = _nu.top();
_nu.pop();
_nu.push( nu2 / nu1 );
break;
case '+':
nu1 = _nu.top();
_nu.pop();
nu2 = _nu.top();
_nu.pop();
_nu.push( nu2 + nu1 );
break;
case '-':
nu1 = _nu.top();
_nu.pop();
nu2 = _nu.top();
_nu.pop();
_nu.push( nu2 - nu1 );
break;
case 'n':
nu1 = _nu.top();
_nu.pop();
_nu.push( sin( nu1 ) );
break;
case 's':
nu1 = _nu.top();
_nu.pop();
_nu.push( cos( nu1 ) );
break;
case 't':
nu1 = _nu.top();
_nu.pop();
_nu.push( tan( nu1 ) );
break;
case '^':
nu1 = _nu.top();
_nu.pop();
nu2 = _nu.top();
_nu.pop();
_nu.push( pow( nu2, nu1 ) );
break;
case '!':
nu1 = _nu.top();
_nu.pop();
_nu.push( fact(nu1) );
break;
case 'g':
nu1 = _nu.top();
_nu.pop();
_nu.push( log(nu1)/log(10) );
break;
case 'r':
nu1 = _nu.top();
_nu.pop();
_nu.push( sqrt( nu1 ) );
break;
default:
break;
}
}
long double fact( long double _number) //阶乘会自动取整,故返回为整数
{
if( _number <0 )return -1;
int n = _number;
long double results = 1;
if( n == 0 )results = 1;
else if( n >= 1)
{
for(int i = 1;i <= n; i++)
results = i * results;
}
return results;
}
char tri_function( char str ) //用于判断三角函数,标记三角函数的最后一个字母,使其变为符号可以入栈,或转换最后一个字符
{ //防止字符重复的情况,如sin和cos的s如果不加判断会重复入栈
char tri;
tri = str;
if( ((str == 's') && (tri_flag != 5)) || (tri_flag == 1) || (tri_flag ==2) ) //sin的s会和cos的s重复判断
{
if(str =='s')tri_flag = 1;
if( (str == 'i') || (tri_flag ==2) )
{
if(str == 'i')tri_flag = 2;
if( str == 'n' )
tri_flag = 3;
}
}
if( (str == 'c') || (tri_flag == 4) || (tri_flag ==5) )
{
if(str == 'c')tri_flag = 4;
if( (str == 'o') || (tri_flag ==5) )
{
if(str == 'o')tri_flag = 5;
if( str == 's' )
tri_flag = 6;
}
}
if( (str == 't') || (tri_flag == 7) || (tri_flag == 8 ))
{
if( str == 't')tri_flag = 7;
if( (str == 'a') || (tri_flag == 8) )
{
if( str == 'a' )tri_flag = 8;
if( str == 'n')
{
tri_flag = 9;
tri = 't';
}
}
}
if( (str == 'l') || (tri_flag == 10) || (tri_flag == 11))
{
if( str == 'l')tri_flag = 10;
if( (str == 'o') || (tri_flag == 11) )
{
if( str == 'o' )tri_flag = 11;
if( str == 'g' )
tri_flag = 12;
}
}
if( ((str == 's') && (tri_flag != 6)) || (tri_flag == 1) || (tri_flag == 14) || (tri_flag == 15))
{ //squrt 和 cos 的s
if( str == 's')tri_flag = 1;
if( (str =='q') || (tri_flag == 14) )
{
if( str == 'q')tri_flag =14;
if( (str == 'r') || (tri_flag == 15))
{
if( str == 't')
{
tri_flag = 16;
tri = 'r';
}
}
}
}
if( (str != 's') && (str != 'i') && (str != 'n') && (str != 'c')
&& (str != 'o') && (str != 't') && (str != 'a') && (str != 'l')
&& (str != 'g') && (str != 'q') && (str != 'r'))
tri_flag = 0;
return tri;
}
void test()
{
char str[] = "-7.8*sin((log(48^2)-48.7/2.56)/(4!))+tan(4.75*cos(log(74*58.2)))";//在这里编辑需要计算的算式
int len = strlen(str);
char str_last = 'z';//用于判断结束
cout<<str<<endl;
for(int i = 0;i < len; i++ )
judge(str[i]);
judge(str_last);
cout<<"op:"<<op.top()<<endl;
cout<<"_nu:"<<_nu.top()<<endl;
getchar();
}
int main()
{
char init_op = '#'; //注意这里不能少,要在符号栈先存入一个#号,防止程序出错时,指空
op.push(init_op);
char init_nu = 0;
_nu.push(init_nu); //在数字栈中输入初始值0,以便判断第一位是否为负数
test();
getchar();
return 0;
}