@Badsignal

Реализация калькулятора: какой алгоритм использовать?

Приветствую! Пишу приложение-калькулятор с бинарными/унарными функциями и скобками. Сейчас всё работает таким образом:

1. Все операнды и операторы кидаются в стек
2. При нажатии кнопки "=" запускается алгоритм сортировочной станции, который дальше считает результат в RPN

Однако задача в том, чтобы можно было видеть некий промежуточный результат, как в стандартных калькуляторах (например, для iPhone). То есть, унарное выражение считается отдельно (при нажатии на квадратный корень при выражении 2 + √(3+6) выводится результат "3", а дальше, если после этого нажать "+", то считается всё выражение с учетом приоритета). А бинарное выражение считается с учетом приоритета и выдает результат всех доступных вычислений (если приоритет следующей операции меньше, чем предыдущей).

Конечно, можно каждый раз при нажатии на бинарную операцию считать заново всё заново (расставляя ограничения по приоритетам), а при нажатии унарной -- считать отдельный регион, но что-то мне кажется, что это не особо оптимально.

Есть какие-нибудь еще варианты?

P.S. Наверное, требуется несколько уточнений:

а). Нынешняя реализация отлично считает готовое выражение;
б). Насколько я видел, калькуляторы считают бинарную операцию только тогда, когда встретилась следующая операция с приоритетом ниже ее (То есть, когда пользователь вводит 2 + 3 * , он не получает результат сложения, потому что нынешняя операция приоритетнее, а если после этого он захочет второй операнд возвести в степень, то отложится вычисление уже двух операций: 2 + 3 * 4 ^ 2);
в). У программы есть GUI, поэтому от нужен некий промежуточный результат;
г). Язык Swift (хотя это неважно, но вдруг);
  • Вопрос задан
  • 2705 просмотров
Решения вопроса 1
@Badsignal Автор вопроса
Вопрос решился.

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

Если будет возможность, выложу решение на GitHub.

Всем спасибо за помощь!
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 3
demon416nds
@demon416nds
Разработчик на чем попало
пересчитывай все сразу
зы лучше будет если будет отображаться так
2 + √(3+6)
2+3
5
Ответ написан
xmoonlight
@xmoonlight
https://sitecoder.blogspot.com
Парсите по операторам слева направо.
2 + √(3+6):
  1. 2 => 2
  2. 2 + => 2
  3. 2 + √ => 2
  4. 2 + √( => 2
  5. 2 + √(3 => 2
  6. 2 + √(3+ => 2
  7. 2 + √(3+6 => 2
  8. 2 + √(3+6) => 2+3 => 5

При валидных выражениях - вычисляйте теми же пунктами ("стек" и RPN).
Слева направо при выемке из стека - заменяйте исходное выражение:
√(3+6) => 3
Валидация выражения на каждом шаге проверяется во время преобразования выражения в стек (в вопросе - п.1).
Ответ написан
skobkin
@skobkin
Гентушник, разработчик на PHP и Symfony.
Вы, наверное, интересуетесь обратной польской нотацией?
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы