数式计算(递归解法)

  1 /**
  2 *注:1.有一个bug(以及未知什么bug) 我已知的是: ([email protected])(ps:@为运算符),这种带括号的表达式不能单独的出现,否则异常退出,,但是只要([email protected])@n
  3
  4 带括号的表达式出现任意+,-,*,/的运算都能进行正常运算(前面 [email protected]([email protected])也不可以)。。。不知道为什么()表达式后面没有操作时会异常退出。
  5 *不知道如何解决。希望感兴趣的人帮帮忙!
  6
  7 //--------------------------------------------
  8 *一般的数式计算(允许括号的)需要通过栈来实现,但是其实对一些新手(我还没学数据结构)来说,用递归其实也是能很好的实现的。而且也很易于理解。
  9 *主要思路是-判断是有括号,无括号情况,有乘除和无乘除。有乘除时将乘除先算,算出来的值取代乘除的算式。
 10 *将括号中的数先算,将算出来的式子的值(括号中也会进行判断是否有无括号,有无乘除)将算出来的数取代原来的算式,然后递归.
 11 *最后的结束条件(判断其中运算符的数量): 只要算一个单一运算符的式子,因为在递归中所有的复杂的式子都被替换成了值。
 12 */
 13
 14 #include<iostream>
 15 #include<cctype>
 16 #include<vector>
 17 #include<cstdlib>
 18 #include<cstring>
 19 #include<string>
 20
 21 #define Jia 100001
 22 #define Jian 100002
 23 #define Chen 100003
 24 #define Chu 100004
 25 #define Qian 100005
 26 #define Hou 100006
 27
 28 using namespace std;
 29
 30 void Exchange(vector<double>& v, string s);   //将字符串转换成double型数
 31 double Calculate_Single(vector<double> v);    //进行数式计算
 32 double Count(double a, double b, double c);   //计算一组算式
 33 double integer(char c,double &rin);           // 将连续数字字符串转换为整数
 34
 35 double integer(char c,double &rin)       // 将连续数字字符串转换为整数
 36 {
 37     rin = rin*10 + (c-‘0‘);
 38     return rin;
 39 }
 40
 41 void Exchange(vector<double>& v, string s)
 42 {
 43     char *p = &s[0];
 44     double re;
 45     while (*p) {
 46         re = 0;
 47         for ( ; *p; ++p) {
 48             if (isdigit(*p))           //如果是数字字符
 49                 integer(*p, re);       //转换成整数
 50             else{
 51                 if (*p == ‘(‘) { v.push_back(Qian); p++;}
 52                 break;
 53             }
 54         }
 55         if (re)
 56             v.push_back(re);
 57         if (*p == ‘\0‘)
 58             break;
 59         p--;
 60         while (*p++) {
 61             if (*p == ‘+‘) { v.push_back(Jia); continue;    }
 62             if (*p == ‘-‘) { v.push_back(Jian); continue;   }
 63             if (*p == ‘*‘) { v.push_back(Chen); continue;   }
 64             if (*p == ‘/‘) { v.push_back(Chu); continue;    }
 65             if (*p == ‘(‘) { v.push_back(Qian); continue;    }
 66             if (*p == ‘)‘) { v.push_back(Hou); continue;    }
 67             if (isdigit(*p))
 68                 break;
 69         }
 70     }
 71     //    cout << re << endl;        //debug
 72 }
 73
 74 double Count(double a, double b, double c) {
 75     if (c == Jia)  return a + b;
 76     if (c == Jian) return a - b;
 77     if (c == Chen) return a * b;
 78     if (c == Chu)  return a / b;
 79     cerr << "运算出错,运算符不为+、-、*、/ !\n";
 80     exit(1);
 81 }
 82
 83 //思路:递归--将乘除,括号这些地方的算式算成值,替换到只有加减的式子中去,最后这个只要算一个只有加减的式子即可
 84 double Calculate_Single(vector<double> v)  //进行数式计算带括号--用递归实现
 85 {
 86     unsigned jia = 0, jian = 0, cheng = 0, chu = 0, qian = 0, hou = 0;
 87     for (auto it = v.begin(); it != v.end(); ++it) {    //遍历v中每个元素,数一共有多少个操作符
 88         if (*it == Jia)    jia++;
 89         else if (*it == Jian) jian++;
 90         else if (*it == Chen) cheng++;
 91         else if (*it == Chu) chu++;
 92         else if (*it == Qian) qian++;
 93         else if (*it == Hou) hou++;
 94     }
 95     //    for (auto t : v)   //debug
 96     //        cout  << t << "\t" << endl;
 97
 98     if (jia + jian + cheng + chu == 1) {       //最后一步--只算一个算式
 99         if (jia == 1) return v[0] + v[2];
100         if (jian == 1) return v[0] - v[2];
101         if (cheng == 1) return v[0] * v[2];
102         if (chu == 1) return v[0] / v[2];
103     }
104    if (qian + hou == 0) {                                                //无括号的情形
105         if (cheng + chu == 0 ) {                                         //无乘除情形
106             vector<double> vv;                                            //对一组数进行操作
107             double re = Count(v[0], v[2], v[1]); //只对一对算式进行操作
108             vv.push_back(re);                                              //将一对算式的结果推入底部,相当于用答案取代了那个算式
109             for (auto i = v.begin() + 3; i != v.end(); ++i) {   //将上一个算式后的所有字符添加vv到底部
110                 vv.push_back(*i);
111             }
112             return Calculate_Single(vv);   //用递归实现--相当于将一处的算式替换成了数字
113         }
114         else {       //有乘除--目标:将指针一直前进到乘/除字符的位置t,计算该算式,保存乘/除前面所有的字符,再保存乘除算成的值,再保存乘除后的算式
115             int t;    //标志位置-乘或除的位置
116             vector<double> vv;  //用来保存计算过乘除的式子
117             for (t = 0; v[t] != Chen && v[t] != Chu; ++t);  //推进到乘除的地方
118             double re = Count(v[t-1], v[t+1], v[t]);           //计算乘除式子
119             for (int i = 0; i < t-1; i++) {                           //将乘除前面的式子push_back
120                 vv.push_back(v[i]);
121             }
122             vv.push_back(re);                                                     //再替换乘除的式子为数值
123             for (auto it = v.begin() + t + 2; it != v.end(); ++it) {  //将乘除后面式子保存到vv中
124                 vv.push_back(*it);
125             }
126             return Calculate_Single(vv);                                       //递归--一直递归到式子中只有一个式子的情况
127         }
128     }
129     else {        //有括号的情况
130         vector<double> vv, vvv;             //vv--是保存将括号中计算结束后的式子,vvv--保存括号中的式子并计算出
131         int q, h;                                     //q -- 前括号的位置,h--后括号的位置
132         double re;
133         for (h = 0; v[h] != Hou; ++h);    //推进到后括号的位置
134         for (q = h; v[q] != Qian; --q);     //后退到前括号的位置
135         for (int i = q + 1; i < h; ++i)       //将括号中的式子push到vvv底部
136             vvv.push_back(v[i]);
137         re = Calculate_Single(vvv);       //将括号中的式子递归求出
138         for (int i = 0; i < q; i++) {        //将前括号中的式子push_back
139             vv.push_back(v[i]);
140         }
141         vv.push_back(re);                                                   //将括号中的式子计算出push到vv底部
142         for (auto it = v.begin() + h + 1; it != v.end(); ++it)  //将括号后的式子push_back
143             vv.push_back(*it);
144         return Calculate_Single(vv);                                    //再次递归进行计算--一直到只有一个式子的时候终止
145     }
146     cerr << "Bug:Calculate_Single 失效!" << endl;
147     return 0;
148 }
149
150 int main()
151 {
152     vector<double> data;
153     string line;
154     cin >> line;
155     Exchange(data, line);
156     double result = Calculate_Single(data);
157     cout << result << endl;
158     return 0;
159 }
时间: 2024-10-21 23:59:01

数式计算(递归解法)的相关文章

NYOJ 128 前缀式计算

前缀式计算 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 先说明一下什么是中缀式: 如2+(3+4)*5这种我们最常见的式子就是中缀式. 而把中缀式按运算顺序加上括号就是:(2+((3+4)*5)) 然后把运算符写到括号前面就是+(2 *( +(3 4) 5) ) 把括号去掉就是:+ 2 * + 3 4 5 最后这个式子就是该表达式的前缀表示. 给你一个前缀表达式,请你计算出该前缀式的值. 比如: + 2 * + 3 4 5的值就是 37 输入 有多组测试数据,每

变形二叉树中节点的最大距离(树的最长路径)——非递归解法

问题描述: 如果我们把二叉树看成一个图,父子节点之间的连线看成是双向的,我们姑且定义"距离"为两节点之间边的个数. 写一个程序,求一棵二叉树中相距最远的两个节点之间的距离.测试用的树: n1 /             \ n2             n3 /        \ n4          n5 /     \         /   \ n6    n7    n8    n9 /                       / n10                

NYOJ--128--前缀式计算(表达式求值)

前缀式计算 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 先说明一下什么是中缀式: 如2+(3+4)*5这种我们最常见的式子就是中缀式. 而把中缀式按运算顺序加上括号就是:(2+((3+4)*5)) 然后把运算符写到括号前面就是+(2 *( +(3 4) 5) ) 把括号去掉就是:+ 2 * + 3 4 5 最后这个式子就是该表达式的前缀表示. 给你一个前缀表达式,请你计算出该前缀式的值. 比如: + 2 * + 3 4 5的值就是 37 输入 有多组测试数据,每

前缀式计算(前缀表达式)

前缀式计算 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 先说明一下什么是中缀式: 如2+(3+4)*5这种我们最常见的式子就是中缀式. 而把中缀式按运算顺序加上括号就是:(2+((3+4)*5)) 然后把运算符写到括号前面就是+(2 *( +(3 4) 5) ) 把括号去掉就是:+ 2 * + 3 4 5 最后这个式子就是该表达式的前缀表示. 给你一个前缀表达式,请你计算出该前缀式的值. 比如: + 2 * + 3 4 5的值就是 37 输入 有多组测试数据,每

NYOJ128 前缀式计算 【栈】

前缀式计算 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描写叙述 先说明一下什么是中缀式: 如2+(3+4)*5这样的我们最常见的式子就是中缀式. 而把中缀式按运算顺序加上括号就是:(2+((3+4)*5)) 然后把运算符写到括号前面就是+(2 *( +(3 4) 5) ) 把括号去掉就是:+ 2 * + 3 4 5 最后这个式子就是该表达式的前缀表示. 给你一个前缀表达式,请你计算出该前缀式的值. 比方: + 2 * + 3 4 5的值就是 37 输入 有多组測试数

大数据流式计算:关键技术及系统实例

孙大为1, 张广艳1,2, 郑纬民1 摘要:大数据计算主要有批量计算和流式计算两种形态,目前,关于大数据批量计算系统的研究和讨论相对充分,而如何构建低延迟.高吞吐且持续可靠运行的大数据流式计算系统是当前亟待解决的问题且研究成果和实践经验相对较少.总结了典型应用领域中流式大数据所呈现出的实时性.易失性.突发性.无序性.无限性等特征,给出了理想的大数据流式计算系统在系统结构.数据传输.应用接口.高可用技术等方面应该具有的关键技术特征,论述并对比了已有的大数据流式计算系统的典型实例,最后阐述了大数据流

前缀式计算

前缀式计算 描述 先说明一下什么是中缀式: 如2+(3+4)*5这种我们最常见的式子就是中缀式. 而把中缀式按运算顺序加上括号就是:(2+((3+4)*5)) 然后把运算符写到括号前面就是+(2 *( +(3 4) 5) ) 把括号去掉就是:+ 2 * + 3 4 5 最后这个式子就是该表达式的前缀表示. 给你一个前缀表达式,请你计算出该前缀式的值. 比如: + 2 * + 3 4 5的值就是 37 输入 有多组测试数据,每组测试数据占一行,任意两个操作符之间,任意两个操作数之间,操作数与操作符

NYOJ128前缀式计算

前缀式计算 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 先说明一下什么是中缀式: 如2+(3+4)*5这种我们最常见的式子就是中缀式. 而把中缀式按运算顺序加上括号就是:(2+((3+4)*5)) 然后把运算符写到括号前面就是+(2 *( +(3 4) 5) ) 把括号去掉就是:+ 2 * + 3 4 5 最后这个式子就是该表达式的前缀表示. 给你一个前缀表达式,请你计算出该前缀式的值. 比如: + 2 * + 3 4 5的值就是 37 输入 有多组测试数据,每

流式计算框架-STORM简介

在当前的数据分析领域,对实时数据的计算需求越来越强烈,在此领域,出现了各类计算框架,如:Storm.S4等.目前本土公司对这些流式计算框架的应用也比较广泛,但苦于相关文档英文居多,缺少成系列且与官方相对应的中文手册.本系列试图从官方文档翻译入手,给大家呈现较为完备的中文资料,同时也是对自身知识的总结沉淀. 在这个系列博客中,我们选择了twitter的Storm框架,原因很简单,因为本人长期使用的就是该框架,咱们先从简介开始. Apache Storm是一个免费.开源.分布式的实时计算系统.相对于