Guest User

Untitled

a guest
Nov 15th, 2018
115
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.90 KB | None | 0 0
  1. #define _USE_MATH_DEFINES
  2. #include <iostream>
  3. #include <string>
  4. #include <algorithm>
  5. #include <map>
  6. #include <cmath>
  7. #include <vector>
  8. #include <fstream>
  9.  
  10. using namespace std;
  11.  
  12. /*
  13. Объявление констант
  14. */
  15. const string operations = "+-*/^!()";
  16. enum LexemType { // используемые лексемы
  17. Plus,
  18. Minus,
  19. Mult,
  20. Div,
  21. Exp,
  22. Factorial,
  23. OpenBracket,
  24. CloseBracket,
  25. Number,
  26. Const,
  27. Func,
  28. End,
  29. Nan,
  30. };
  31. const double delta = 1e-6; // для сравнение вещественных чисел
  32. // map - хеш-таблица - для отображения строки в математическую функцию
  33. const map<string, double(*)(double)> functions = {
  34. { "sin", &sin },
  35. { "cos", &cos },
  36. { "tg", &tan },
  37. { "ln", &log }
  38. };
  39. const map<string, double> constants = {
  40. { "pi", M_PI },
  41. { "e", M_E }
  42. };
  43.  
  44. /*
  45. Текущее состояние вычислительного процесса
  46. */
  47. int currentPosition = 0;
  48. string expression; // 1 строка
  49. LexemType currentLexem;
  50. string currentLexemValue; // значение лексемы - только для ф-ций, чисел (и констант)
  51.  
  52. void skipSpaces() {
  53. while (currentPosition < expression.size() && expression[currentPosition] == ' ') {
  54. currentPosition++;
  55. }
  56. }
  57.  
  58. bool isNumber(const string& str) {
  59. for (int i = 0; i < str.size(); ++i) {
  60. if (!isdigit(str[i]) && str[i] != '.') {
  61. return false;
  62. }
  63. }
  64. return count(str.begin(), str.end(), '.') <= 1;
  65. }
  66.  
  67. bool isConstant(const string& str) { // в поисках pi / e
  68. return (constants.find(str) != constants.end());
  69. }
  70.  
  71. bool isFunc(const string& str) { // в поисках функций
  72. return (functions.find(str) != functions.end());
  73. }
  74.  
  75. double toNum(const string& str) { // перевод вещественного числа из строки в double
  76. return stod(str);
  77. }
  78.  
  79. long factorial(int n) {
  80. if (n < 0)
  81. return 0;
  82.  
  83. long result = 1;
  84. while (n > 0) {
  85. if (result < 0) {
  86. return -1;
  87. }
  88. result *= n;
  89. n--;
  90. }
  91. return result;
  92. }
  93.  
  94. void nextLexem() { // перенос currentLexem не след лексему
  95. skipSpaces();
  96. // проверка конца выражения
  97. if (currentPosition == expression.size()) {
  98. currentLexem = End;
  99. return;
  100. }
  101.  
  102. char ch = expression[currentPosition];
  103. int position = operations.find(ch); // находим позицию ch - номер операции - с 0
  104. if (position != -1) { // нашли
  105. currentLexem = (LexemType)position; // преобразовываем порядковый номер в тип лексемы
  106. currentPosition++;
  107. return;
  108. }
  109.  
  110. // число или функция или константа
  111. currentLexemValue.clear();
  112. while (currentPosition < expression.size() && (isalnum(ch) || ch == '.')) { // isalnum - проверка, буква или число
  113. currentLexemValue += expression[currentPosition]; // посимвольно добавляем
  114. currentPosition++;
  115. ch = expression[currentPosition]; // перешли на новую позицию, считали символ
  116. }
  117.  
  118. if (isNumber(currentLexemValue)) {
  119. currentLexem = Number;
  120. }
  121. else if (isConstant(currentLexemValue)) {
  122. currentLexem = Const;
  123. }
  124. else if (isFunc(currentLexemValue)) {
  125. currentLexem = Func;
  126. }
  127. else {
  128. currentLexem = Nan;
  129. }
  130. }// currentLexem - тип текущей лексемы, currentLexemValue - ее значение, если можно вычислить
  131.  
  132. bool calculateExpression(double& result); // прототип функции
  133. bool calculateFunction(double& result) {
  134. string funcName = currentLexemValue;
  135. nextLexem();
  136. if (currentLexem != OpenBracket) { // если у функции нет открывающейся скобки
  137. return false;
  138. }
  139. nextLexem();
  140. double arg = 0.0;
  141. if (!calculateExpression(arg)) { // считаем выражение в скобках
  142. return false;
  143. }
  144. result = functions.at(funcName)(arg); // заменяем functions.at(funcName) на название функции
  145. if (isnan(result) || isinf(result)) {
  146. return false;
  147. }
  148. return true;
  149. }
  150.  
  151. bool calculateSubfactorial(double& result) { // вычисляем подфакториальное выражение
  152. // bool isNegative = false;
  153. // if (currentLexem == Plus || currentLexem == Minus) {
  154. // isNegative = currentLexem == Minus;
  155. // nextLexem();
  156. // }
  157. switch (currentLexem) {
  158. case OpenBracket: {
  159. nextLexem();
  160. if (!calculateExpression(result)) {
  161. return false;
  162. }
  163. if (currentLexem != CloseBracket) {
  164. return false;
  165. }
  166. nextLexem();
  167. break;
  168. }
  169. case Func: {
  170. if (!calculateFunction(result)) {
  171. return false;
  172. }
  173. if (currentLexem != End) {
  174. nextLexem();
  175. }
  176. break;
  177. }
  178. case Const: {
  179. result = constants.at(currentLexemValue);
  180. nextLexem();
  181. break;
  182. }
  183. case Number: {
  184. result = toNum(currentLexemValue);
  185. nextLexem();
  186. break;
  187. }
  188. default:
  189. return false;
  190. }
  191. //result *= isNegative ? -1 : 1;
  192. return true;
  193. }
  194.  
  195. bool calculateExponentBase(double& result) {
  196. if (!calculateSubfactorial(result)) {
  197. return false;
  198. }
  199. if (currentLexem == Factorial) {
  200. if (abs((int)result - result) < delta) { // определяем, вещественное число или целое
  201. result = (double)factorial((int)result); // считаем факториал
  202. if ((int)result == -1) {
  203. return false;
  204. }
  205. }
  206. else { // если вещественное
  207. return false;
  208. }
  209. nextLexem();
  210. }
  211. return true;
  212. }
  213.  
  214. bool calculateMultiplier(double& result) {
  215. if (!calculateExponentBase(result)) {
  216. return false;
  217. }
  218. if (currentLexem == Exp) {
  219. nextLexem();
  220. double next = 0.0;
  221. if (!calculateMultiplier(next)) {
  222. return false;
  223. }
  224.  
  225. result = pow(result, next); // возводим результат в степень
  226. }
  227. return true;
  228. }
  229.  
  230. bool calculateAddend(double& result) { // вычисление слагаемого
  231. if (!calculateMultiplier(result)) {
  232. return false;
  233. }
  234. while (currentLexem == Mult || currentLexem == Div) {
  235. LexemType operation = currentLexem;
  236. nextLexem();
  237. double next = 0.0;
  238. if (!calculateMultiplier(next)) {
  239. return false;
  240. }
  241. switch (operation) {
  242. case Mult:
  243. result *= next;
  244. break;
  245. case Div:
  246. result /= next;
  247. break;
  248. default:
  249. return false;
  250. }
  251. }
  252. return true;
  253. }
  254.  
  255. bool calculateExpression(double& result) {
  256. bool isNegative = false;
  257. if (currentLexem == Plus || currentLexem == Minus) { // проверка, есть ли "-" перед выражением
  258. isNegative = currentLexem == Minus;
  259. nextLexem();
  260. }
  261. if (!calculateAddend(result)) {
  262. return false;
  263. } // считаем 1е слагаемое - оно всегда есть мин 1
  264. while (currentLexem == Plus || currentLexem == Minus) {
  265. LexemType operation = currentLexem;
  266. nextLexem();
  267. double next = 0.0; // сумма 2+ слагаемых
  268. if (!calculateAddend(next)) {
  269. return false;
  270. } // считаем следующее слагаемое
  271. switch (operation) {
  272. case Plus:
  273. result += next;
  274. break;
  275. case Minus:
  276. result -= next;
  277. break;
  278. default:
  279. return false;
  280. }
  281. }
  282. result *= isNegative ? -1 : 1; // домножаем на -1 если были "-" перед выражением
  283. return currentLexem == End || currentLexem == CloseBracket; // конец выражения - просто конец либо закрывающаяся скобка
  284. }
  285.  
  286. string solve(const string& expr) {
  287. if (expr.length() == 0) {
  288. return "";
  289. }
  290.  
  291. // инициализация глобальных переменных
  292. expression = expr;
  293. currentLexem = Nan;
  294. currentLexemValue.clear();
  295. currentPosition = 0;
  296.  
  297. nextLexem(); // переходим на новую лексему
  298. double result = 0.0;
  299. if (calculateExpression(result)) {// решили выражение
  300. return to_string(result);
  301. } else {
  302. return "Error";
  303. }
  304. }
  305.  
  306. void input(const string& filename, vector<string>& vect) {
  307. ifstream fin(filename); // открываем поток ввода
  308. if (!fin) {
  309. cout << "File cannot be opened!" << endl;
  310. return;
  311. }
  312. string buffer;
  313. while (getline(fin, buffer)) {
  314. vect.push_back(buffer);
  315. }
  316. fin.close();
  317. }
  318.  
  319. void output(const string& filename, vector<string>& vect) {
  320. ofstream fout(filename);
  321. if (!fout) {
  322. cout << "File cannot be opened!" << endl;
  323. return;
  324. }
  325. for (string expr : vect) { // цикл проходит по каждому элементу вектора
  326. fout << expr << endl;
  327. }
  328. fout.close();
  329. }
  330.  
  331. int main() {
  332. // vector<string> expressions; // вектор - расширяемый массив - все считанные строки
  333. // vector<string> results;
  334. // input("in.txt", expressions);
  335. // for (string expr : expressions) { // для каждого expr в expressions - перебор всех элементов
  336. // results.push_back(solve(expr)); // добавление вычислений в вектор результатов
  337. // }
  338. // output("out.txt", results);
  339. cout << solve("111!") << endl;
  340. return 0;
  341. }
  342. // 1. Триганометрические функции
  343. // 2. Факториал
  344. // 3. Степень
  345. // 4. Умножение/деление
  346. // 5. +-
Add Comment
Please, Sign In to add comment