基于逆波兰算法的计算方法C++程序(计算器算法)

主要有以下功能:可以连续计算四则运算,可以自己分辨多位数,小数,负数。

后续会加入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;
}

 

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值