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