Есть два консольных калькулятора. Оба принимают текстовую строку как входное выражение и возвращают результат вычислений.
Первый перед вычислением рекурсивно (можно и итеративно) строит дерево, листья которого - положительные действительные числа, а остальные узлы - операции. Для построения дерева приоритет операций инвертируется - сначала выбираются операции с
наименьшим приоритетом, не разбивая скобок. После выбора операции выражение разбивается на две части по знаку операции - операнды. Выражения-операнды рассматриваются как отдельные выражения: их разбиение продолжается независимо друг от друга. При получении результата вычисления двух операндов-выражений над полученными значениями выполняется операция. Результат операции возвращается.
Алгоритм одного вызова функции разбора Calc(String expr):
- Поиск операций в expr с учётом приоритета и сохранения скобочной структуры; или преобразование строки в число и возврат значения.
- Разбиение expr на два подвыражения по найденному знаку операции - oper1, oper2
- Рекурсивное разбиение: res1 = Calc(oper1); res2 = Calc(oper2);
- Вычисление результата найденной операции над res1 и res2 - o_res.
- Возвращение o_res.
При этом
второй калькулятор работает с выражением "как в школе", модифицируя строку: выбирает
элементарную операцию (операнды - числа) с
наибольшим приоритетом, вычисляет её значение, заменяет выражение значением, получая упрощённое выражение и повторяет процедуру до получения валидного числа, которое можно привести и вернуть.
Какой из этих подходов лучше? Какие "подводные камни"?Есть ли более подходящие альтернативы?