Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define _USE_MATH_DEFINES
- #include <iostream>
- #include <string>
- #include <algorithm>
- #include <map>
- #include <cmath>
- #include <vector>
- #include <fstream>
- using namespace std;
- /*
- Объявление констант
- */
- const string operations = "+-*/^!()";
- enum LexemType { // используемые лексемы
- Plus,
- Minus,
- Mult,
- Div,
- Exp,
- Factorial,
- OpenBracket,
- CloseBracket,
- Number,
- Const,
- Func,
- End,
- Nan,
- };
- const double delta = 1e-6; // для сравнение вещественных чисел
- // map - хеш-таблица - для отображения строки в математическую функцию
- const map<string, double(*)(double)> functions = {
- { "sin", &sin },
- { "cos", &cos },
- { "tg", &tan },
- { "ln", &log }
- };
- const map<string, double> constants = {
- { "pi", M_PI },
- { "e", M_E }
- };
- /*
- Текущее состояние вычислительного процесса
- */
- int currentPosition = 0;
- string expression; // 1 строка
- LexemType currentLexem;
- string currentLexemValue; // значение лексемы - только для ф-ций, чисел (и констант)
- void skipSpaces() {
- while (currentPosition < expression.size() && expression[currentPosition] == ' ') {
- currentPosition++;
- }
- }
- bool isNumber(const string& str) {
- for (int i = 0; i < str.size(); ++i) {
- if (!isdigit(str[i]) && str[i] != '.') {
- return false;
- }
- }
- return count(str.begin(), str.end(), '.') <= 1;
- }
- bool isConstant(const string& str) { // в поисках pi / e
- return (constants.find(str) != constants.end());
- }
- bool isFunc(const string& str) { // в поисках функций
- return (functions.find(str) != functions.end());
- }
- double toNum(const string& str) { // перевод вещественного числа из строки в double
- return stod(str);
- }
- long factorial(int n) {
- if (n < 0)
- return 0;
- long result = 1;
- while (n > 0) {
- if (result < 0) {
- return -1;
- }
- result *= n;
- n--;
- }
- return result;
- }
- void nextLexem() { // перенос currentLexem не след лексему
- skipSpaces();
- // проверка конца выражения
- if (currentPosition == expression.size()) {
- currentLexem = End;
- return;
- }
- char ch = expression[currentPosition];
- int position = operations.find(ch); // находим позицию ch - номер операции - с 0
- if (position != -1) { // нашли
- currentLexem = (LexemType)position; // преобразовываем порядковый номер в тип лексемы
- currentPosition++;
- return;
- }
- // число или функция или константа
- currentLexemValue.clear();
- while (currentPosition < expression.size() && (isalnum(ch) || ch == '.')) { // isalnum - проверка, буква или число
- currentLexemValue += expression[currentPosition]; // посимвольно добавляем
- currentPosition++;
- ch = expression[currentPosition]; // перешли на новую позицию, считали символ
- }
- if (isNumber(currentLexemValue)) {
- currentLexem = Number;
- }
- else if (isConstant(currentLexemValue)) {
- currentLexem = Const;
- }
- else if (isFunc(currentLexemValue)) {
- currentLexem = Func;
- }
- else {
- currentLexem = Nan;
- }
- }// currentLexem - тип текущей лексемы, currentLexemValue - ее значение, если можно вычислить
- bool calculateExpression(double& result); // прототип функции
- bool calculateFunction(double& result) {
- string funcName = currentLexemValue;
- nextLexem();
- if (currentLexem != OpenBracket) { // если у функции нет открывающейся скобки
- return false;
- }
- nextLexem();
- double arg = 0.0;
- if (!calculateExpression(arg)) { // считаем выражение в скобках
- return false;
- }
- result = functions.at(funcName)(arg); // заменяем functions.at(funcName) на название функции
- if (isnan(result) || isinf(result)) {
- return false;
- }
- return true;
- }
- bool calculateSubfactorial(double& result) { // вычисляем подфакториальное выражение
- // bool isNegative = false;
- // if (currentLexem == Plus || currentLexem == Minus) {
- // isNegative = currentLexem == Minus;
- // nextLexem();
- // }
- switch (currentLexem) {
- case OpenBracket: {
- nextLexem();
- if (!calculateExpression(result)) {
- return false;
- }
- if (currentLexem != CloseBracket) {
- return false;
- }
- nextLexem();
- break;
- }
- case Func: {
- if (!calculateFunction(result)) {
- return false;
- }
- if (currentLexem != End) {
- nextLexem();
- }
- break;
- }
- case Const: {
- result = constants.at(currentLexemValue);
- nextLexem();
- break;
- }
- case Number: {
- result = toNum(currentLexemValue);
- nextLexem();
- break;
- }
- default:
- return false;
- }
- //result *= isNegative ? -1 : 1;
- return true;
- }
- bool calculateExponentBase(double& result) {
- if (!calculateSubfactorial(result)) {
- return false;
- }
- if (currentLexem == Factorial) {
- if (abs((int)result - result) < delta) { // определяем, вещественное число или целое
- result = (double)factorial((int)result); // считаем факториал
- if ((int)result == -1) {
- return false;
- }
- }
- else { // если вещественное
- return false;
- }
- nextLexem();
- }
- return true;
- }
- bool calculateMultiplier(double& result) {
- if (!calculateExponentBase(result)) {
- return false;
- }
- if (currentLexem == Exp) {
- nextLexem();
- double next = 0.0;
- if (!calculateMultiplier(next)) {
- return false;
- }
- result = pow(result, next); // возводим результат в степень
- }
- return true;
- }
- bool calculateAddend(double& result) { // вычисление слагаемого
- if (!calculateMultiplier(result)) {
- return false;
- }
- while (currentLexem == Mult || currentLexem == Div) {
- LexemType operation = currentLexem;
- nextLexem();
- double next = 0.0;
- if (!calculateMultiplier(next)) {
- return false;
- }
- switch (operation) {
- case Mult:
- result *= next;
- break;
- case Div:
- result /= next;
- break;
- default:
- return false;
- }
- }
- return true;
- }
- bool calculateExpression(double& result) {
- bool isNegative = false;
- if (currentLexem == Plus || currentLexem == Minus) { // проверка, есть ли "-" перед выражением
- isNegative = currentLexem == Minus;
- nextLexem();
- }
- if (!calculateAddend(result)) {
- return false;
- } // считаем 1е слагаемое - оно всегда есть мин 1
- while (currentLexem == Plus || currentLexem == Minus) {
- LexemType operation = currentLexem;
- nextLexem();
- double next = 0.0; // сумма 2+ слагаемых
- if (!calculateAddend(next)) {
- return false;
- } // считаем следующее слагаемое
- switch (operation) {
- case Plus:
- result += next;
- break;
- case Minus:
- result -= next;
- break;
- default:
- return false;
- }
- }
- result *= isNegative ? -1 : 1; // домножаем на -1 если были "-" перед выражением
- return currentLexem == End || currentLexem == CloseBracket; // конец выражения - просто конец либо закрывающаяся скобка
- }
- string solve(const string& expr) {
- if (expr.length() == 0) {
- return "";
- }
- // инициализация глобальных переменных
- expression = expr;
- currentLexem = Nan;
- currentLexemValue.clear();
- currentPosition = 0;
- nextLexem(); // переходим на новую лексему
- double result = 0.0;
- if (calculateExpression(result)) {// решили выражение
- return to_string(result);
- } else {
- return "Error";
- }
- }
- void input(const string& filename, vector<string>& vect) {
- ifstream fin(filename); // открываем поток ввода
- if (!fin) {
- cout << "File cannot be opened!" << endl;
- return;
- }
- string buffer;
- while (getline(fin, buffer)) {
- vect.push_back(buffer);
- }
- fin.close();
- }
- void output(const string& filename, vector<string>& vect) {
- ofstream fout(filename);
- if (!fout) {
- cout << "File cannot be opened!" << endl;
- return;
- }
- for (string expr : vect) { // цикл проходит по каждому элементу вектора
- fout << expr << endl;
- }
- fout.close();
- }
- int main() {
- // vector<string> expressions; // вектор - расширяемый массив - все считанные строки
- // vector<string> results;
- // input("in.txt", expressions);
- // for (string expr : expressions) { // для каждого expr в expressions - перебор всех элементов
- // results.push_back(solve(expr)); // добавление вычислений в вектор результатов
- // }
- // output("out.txt", results);
- cout << solve("111!") << endl;
- return 0;
- }
- // 1. Триганометрические функции
- // 2. Факториал
- // 3. Степень
- // 4. Умножение/деление
- // 5. +-
Add Comment
Please, Sign In to add comment