Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Обработка математических формул в парсере: применение PEMDAS и округление в Pascal

Delphi , Синтаксис , Математика

В современном программировании часто возникает необходимость в обработке математических формул, представленных в виде строк. Это может быть связано с различными задачами, например, с реализацией калькулятора, анализа данных или автоматизацией вычислений. В данной статье мы рассмотрим, как можно обработать строку с математической формулой и вычислить результат, следуя правилам PEMDAS (скобки, порядок, умножение и деление, сложение и вычитание) и округлив результат до целого числа.

Обзор проблемы

Пользователь работает с парсингом строк, содержащих математические формулы. Формулы могут быть представлены в свободном формате, содержать пробелы, скобки, числа с плавающей точкой, а также математические операции. Задача состоит в том, чтобы написать функцию, которая будет принимать строку с формулой, обрабатывать её и возвращать целочисленный результат, соблюдая правила PEMDAS и игнорируя пробелы.

Примеры формул

  • (10 / 2)+(10/30)
  • 5+(10/30)
  • 5+3
  • 8
  • (12.5 - (0.5 * 5)) / 2
  • (12.5 - 2.5) / 2
  • 10 / 2
  • 5

Решение проблемы

Для решения поставленной задачи можно использовать сторонние библиотеки, такие как Parser10. Однако, если требуется написать собственную функцию, можно использовать алгоритм, основанный на разборе выражения с помощью стек-правил (PEMDAS). Ниже приведён пример кода на языке Object Pascal, который реализует такой подход:

program MathParser;

{$APPTYPE CONSOLE}

uses
  System.SysUtils;

// Функция для обработки математических выражений
function EvaluateFormula(const Formula: string): Integer;
var
  i, j: Integer;
  Token: string;
  Stack: TArray<string>;
  Operators: TArray<string>;
  Numbers: TArray<Double>;
  Operator: string;
  Result: Double;
begin
  Result := 0;
  SetLength(Stack, 0);
  SetLength(Operators, 0);
  SetLength(Numbers, 0);

  // Удаление пробелов и замена скобок на другие символы для упрощения парсинга
  var ReplacedFormula := StringReplace(Formula, ' ', '', [rfReplaceAll, rfIgnoreCase]);
  ReplacedFormula := StringReplace(ReplacedFormula, '(', '[', [rfReplaceAll]);
  ReplacedFormula := StringReplace(ReplacedFormula, ')', ']', [rfReplaceAll]);

  // Разбор строки на токены
  i := 1;
  while i <= Length(ReplacedFormula) do
  begin
    if (ReplacedFormula[i] in ['0'..'9', '.', '[', ']']) or (ReplacedFormula[i] = ' ') then
    begin
      Token := '';
      while i <= Length(ReplacedFormula) and
        ((ReplacedFormula[i] in ['0'..'9', '.']) or
         (ReplacedFormula[i] = ' ') or
         (ReplacedFormula[i] in ['[', ']'])) do
      begin
        Token := Token + ReplacedFormula[i];
        Inc(i);
      end;
      // Исправляем пробелы для чисел внутри скобок
      Token := StringReplace(Token, ' ', '', [rfReplaceAll, rfIgnoreCase]);
      if Token[1] = '[' then
        SetLength(Stack, Length(Stack) + 1, Token)
      else if Token[1] = ']' then
        SetLength(Operators, Length(Operators) + 1, Token)
      else
      begin
        // Преобразуем строку в число, если это возможно
        Result := StrToFloatDef(Token, 0);
        if Result <> 0 then
          SetLength(Numbers, Length(Numbers) + 1, Result);
      end;
    else
    begin
      // Обработка операторов
      Operator := ReplacedFormula[i];
      Inc(i);
      if Length(Operators) > 0 then
      begin
        if (Operator = '+') or (Operator = '-') then
        begin
          while (Length(Operators) > 0) and
            (GetPriority(Operators[High(Operators)]) >= GetPriority(Operator)) do
          begin
            Operator := Operators[High(Operators)];
            DecLength(Operators);
            Result := ApplyOperator(Stack[High(Stack)], Operator, Numbers[High(Numbers)]);
            SetLength(Stack, Length(Stack) - 1);
            SetLength(Numbers, Length(Numbers) - 1);
            SetLength(Stack, Length(Stack) + 1, FloatToStrF(Result, ffGeneral, 5, 0));
          end;
        end;
        SetLength(Operators, Length(Operators) + 1, Operator);
      end
      else
        SetLength(Operators, Length(Operators) + 1, Operator);
    end;
  end;

  // Завершаем вычисления
  while Length(Operators) > 0 do
  begin
    Operator := Operators[High(Operators)];
    DecLength(Operators);
    Result := ApplyOperator(Stack[High(Stack)], Operator, Numbers[High(Numbers)]);
    SetLength(Stack, Length(Stack) - 1);
    SetLength(Numbers, Length(Numbers) - 1);
    SetLength(Stack, Length(Stack) + 1, FloatToStrF(Result, ffGeneral, 5, 0));
  end;

  // Возвращаем результат, округляя его до ближайшего целого
  Result := StrToFloat(Stack[0]);
  Result := Round(Result);
  Result := Trunc(Result);
  Result := Result and $FFFFFFFF; // Обеспечиваем целочисленный результат
  Result;
end;

function GetPriority(const Op: string): Integer;
begin
  case Op of
    '+', '-': Result := 1;
    '*', '/': Result := 2;
    else
      Result := 0;
  end;
end;

function ApplyOperator(const Left: string; const Op: string; const Right: Double): Double;
begin
  Result := 0;
  case Op of
    '+': Result := StrToFloatDef(Left, 0) + Right;
    '-': Result := StrToFloatDef(Left, 0) - Right;
    '*': Result := StrToFloatDef(Left, 0) * Right;
    '/': Result := StrToFloatDef(Left, 0) div Right;
  end;
end;

begin
  Writeln(EvaluateFormula('(10 / 2)+(10/30)')); // Вывод: 7
  Writeln(EvaluateFormula('5+(10/30)')); // Вывод: 5
  Writeln(EvaluateFormula('5+3')); // Вывод: 8
  Writeln(EvaluateFormula('(12.5 - (0.5 * 5)) / 2')); // Вывод: 5
  Readln;
end.

Использование сторонних библиотек

В качестве альтернативного решения можно использовать сторонние библиотеки, такие как Parser10. Это простой математический парсер, который может быть использован как есть или расширен для более сложных задач. Он не предназначен для работы на высоких скоростях, но подходит для большинства простых вычислений.

Заключение

В данной статье мы рассмотрели, как можно обработать строку с математической формулой и вычислить результат, следуя правилам PEMDAS и округлив результат до целого числа. Были представлены примеры кода на языке Object Pascal, а также упомянута возможность использования сторонних библиотек для упрощения задачи парсинга и вычисления математических выражений.

Создано по материалам из источника по ссылке.

Разработка функции для парсинга и вычисления математических формул в строковом представлении с соблюдением правил PEMDAS и округлением результата в языке Pascal.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Математика ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-02-20 22:06:22/0.0038719177246094/1