逆波兰式的计算(含有数学函数和浮点数)

本文探讨了逆波兰表示法(RPN)的计算原理,特别是在处理包含数学函数和浮点数的情况。文章详细介绍了如何利用栈来解析和计算这种表达式,并通过实例展示了计算过程。同时,还讨论了浮点数精度问题及其解决方案。
摘要由CSDN通过智能技术生成
这里的实现较为简单,也只能处理没有嵌套的表达式的情况。
相对完善的代码请见另一篇博客--完整的逆波兰式计算,修正了函数嵌套时出现的问题,调整的一定的
处理方式,使得代码更加简洁。不过大体思路与本代码基本相同。


//本代码提供的测试数据
//9.4+(3.27-1.05)*3.44+10/2.1+cos(0.52)+ln(3)/log(5)+3^2


#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#define MAX 100
#define MARK 65535

typedef struct {
	char data[MAX];
	int top;
}SqStack;

SqStack *initStack(void);
void destroyStack(SqStack *S);
void creatStack(SqStack *S);
void printStack(SqStack *S); 
void changeRpn(SqStack *S,SqStack *rpn);                        //先形式上转化为逆波兰式
int rpnStack(SqStack *rpn,double num[MAX],int loc[MAX],int stack[MAX],char *mark);         //产生一个形式逆波兰式存在 stack 中 
double conduct(char mark[MAX],double num[MAX],int stack[MAX],int stacklen);              //利用逆波兰式计算算式结果并返回 

//处理逆波兰式的方法
//规则:从左到右遍历表达式的每个数字和符号,遇到是数字就进栈,遇到是符号,就将处于栈顶两个数字出栈,进行运算,运算结果进栈,一直到最终获得结果。 
double conduct(char mark[MAX],double num[MAX],int stack[MAX],int stacklen)
{
	double temp[MAX];                //用来存放中间计算过程的栈 
	int j = 0;                       //索引 temp 
	int p = 0;                       //索引 符号栈 mark 
	//int marklen = strlen(mark);       
	for(int i = 0;i<stacklen;i++)     //遍历逆波兰式求值 
	{
		if(stack[i] == MARK)          //如果是操作符,取栈顶两个元素进行计算并存入栈中 
		{
			double x = temp[j-1];     //得到栈顶的两个数 (记住 是前一个数对后一个数操作 ) 
			double y = temp[j-2];
			j = j-2;
			if(mark[p] == '+')
			{
				temp[j++] = x+y;
			}
			else if(mark[p] == '-')
			{
				temp[j++] = y-x;
			}
			else if(mark[p] == '*')
			{
				temp[j++] = x*y;
			}
			else if(mark[p] == '/')
			{
				temp[j++] = y/x;
			}
			
			p++;      //符号栈指针下移 
		}
		else          //若是数字则直接进临时栈 
		{
			temp[j++] = num[stack[i]];
		}
	}
	
	return temp[0];           //返回运算结果 
}
 

int rpnStack(SqStack *rpn,double num[MAX],int loc[MAX],int stack[MAX],char *mark)
{
	int lenloc = 0;
	for(int i = 0;i<=rpn->top;i++)          //定位出空格的位置 
	{
		if(rpn->data[i] == ' ')
		loc[lenloc++] = i;
	}
	
	
	//将计算需要用到的数字全都存放在 num 数组中 
	int count1 = 0,count2 = 0;            //两个 count 用来记两个空格之间的差值,前面ver2时提到,两个空格之间有且仅有一个操作数 
	char a[MAX];                          //用来将串转化成浮点数的临时数组 -- 记住,每次使用前都要初始化 
	int numlen = 0;                       //直接用 numlen 记出 操作数的个数 
	for(int i = 0;i<lenloc;i++)
	{
		count1 = loc[i];                  //先用 count1 定位到后一个空格的位置 
		memset(a,0,sizeof(a));            //初始化 a 数组 
		                        
		if(count1-count2>=1)              //如果两个空格之间有数字 -- 防止多个空格连续的情况 
		{
			int p = 0;                    //用来往 a 数组里存字符的下标,每次用完要重置 0 
			while(count2<count1)
			{
				if(rpn->data[count2] == '.' || (rpn->data[count2] >= '0'&&rpn->data[count2] <= '9'))  //如果是数字或小数点 -- 可能是乘方或存操作数,需要区分 
		    	{
		    		int k = count2;
		    	    while(rpn->data[k]>='0'&&rpn->data[k]<='9' || rpn->data[k] == '.')     //先找下一个非数字和小数点的字符 
			            k++;
			        
					if(rpn->data[k] == '^')           
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值