另一篇關於我在 CodeWars 上的冒險經歷的文章。為此,我們實現了基本計算器的功能:創建一個簡單的計算器,給出一串運算子 ()、+、-、*、/。 我的JavaRush只有10+級,所以程式碼相當繁瑣,但功能完美。您可能已經注意到,該任務來自CodeWars網站。她的等級是3kyu。我可以私訊給你連結。 以下是對我有幫助的方法和過程的部分清單:
- 遞迴. 在這種情況下,方法呼叫自身的過程(第一次使用它:))對於擺脫括號是必要的。
- 方法'
String
atrim()
,,, .split()
_substring()
replace()
- 基本採集方法
List
。 - 以及型別
Double
轉換String
。
* > / > + > -
,但我意識到,例如,使用此選項:12/6 * 32/2
,程式將首先執行乘法(6*32
),一切都會走下坡路,所以順序就變成了這樣:* > / > + > -
。又過了幾個小時,我發現了最大的卵石 - -
。在不同的位置,不同的組合,他改變了一切。(這當然是我的錯,因為,例如:-34
,不在列表的一個單元格中,而是在兩個單元格中:在一個單元格中,-
在另一個單元格中,34
)。因此,我們必須在計算中編寫 2 個額外的邏輯-
,一般來說,您會在程式碼中看到這一點。我對程式碼中不必要的註釋表示歉意,我想盡可能地揭示我的思路並解釋那裡發生的事情。
import java.util.*;
public class Calculator {
public static void main(String[] args) {
String num = "2 / ( ( 2 + 0 ) * 1 ) - 6";
System.out.println(evaluate(num));
}
public static Double evaluate(String expression) {
// Этап 1
// На данном этапе преобразуем нашу строку в список строк, через совмещение цикла for-each и метода split(),
// также используем метод trim(), чтобы избавиться от пробелов по краям.
// Обратите внимание, что каждым вторым элиментом я добавляю " ". Для того, чтобы потом мне было легче работать со строкой
List<string> strList = new ArrayList<>();
for (String listElement : expression.trim().split(" ")) {
strList.add(listElement);
strList.add(" ");
}
strList.remove(strList.size() - 1);
// for (String x : strList) System.out.print(x + "");
// System.out.println();
// После того, How дочитаете code до конца, расскоментируйте две верхние строчки
// и посмотрите How работает рекрусия
// Этап 2
// Производим поиск символа "(" в списке если находим, то преобразуем все символы от '(' до последнего ')' в строку.
// Надо быть внимательными и проверить на случай двух контрукций: 1) (()) 2) ()().
// P.S. После получения строки мы используем РЕКУРСИЮ (метод вызывает сам себя). Таким образом будем находить произведение скобок.
if (strList.indexOf("(") != -1) {
// Если "(" обнаружен, ищем подходящую конструкцию используя цикл.
for (int i = strList.indexOf("(") + 1; i < strList.size() - 1; i++) {
//
// Конструкция 1: первым элиментом, который мы отыскали были вторые "("
String recursion = "";
if (strList.get(i).equals("(")) {
for (int j = i; j < strList.lastIndexOf(")"); j++) {
recursion += strList.get(j);
}
// сверху считывали последовательность находящуюся в скобках (()) До lastIndex element
String test = expression.substring(expression.indexOf("("), expression.lastIndexOf(")") + 1);
// test - последовательность How и сверху, но с добавлением скобок по краям
// т.к. наш метод evaluate() возвращает Double, мы должны преобразовать результат рекрусии в String;
String testRecursion = String.valueOf(evaluate(recursion));
expression = expression.replace(test, testRecursion);
// преобразовали нашу строку с использование рекруси. Избавorсь от первых скобок
strList.removeAll(strList);
for (String newElement : expression.trim().split(" ")) {
strList.add(newElement);
strList.add(" ");
}
// Тут очищаем наш список и сново его заполняем (но уже раскрыв первые скобки)
}
// Конструкция 2: первым элиментом, который мы отыскали был ")"
String recursion2 = "";
if (strList.get(i).equals(")")) {
for (int j = strList.indexOf("(") + 1; j < strList.indexOf(")"); j++) {
recursion2 += strList.get(j);
}
String test2 = expression.substring(expression.indexOf("("), expression.lastIndexOf(")") + 1);
String testRecursion2 = String.valueOf(evaluate(recursion2));
expression = expression.replace(test2, testRecursion2);
for (String newElement : expression.trim().split(" ")) {
strList.add(newElement);
strList.add(" ");
}
// Тут повторor тот же алгоритм, что и в первой конструкции
}
}
}
// Этап 3
// Заключительный этап на котором мы будем реализовывать сами вычесления (*/-+)
// Всю реализацию помещаем в цикл while ( который прекратиться, если все действия будут выполнены (соответственно в списке останется 1 элемент)).
// Внимательно посмотрите на порядок операций: 1)/ 2)* 3)- 4)+
// System.out.println(expression + "-------expression-");
// System.out.println();
// создаем очередной список для реализации вычеслений, на этот раз без добавления " ".
List<string> stringList2 = new ArrayList<>();
for (String element : expression.trim().split(" ")) {
stringList2.add(element);
}
while (stringList2.size() != 0) {
// работаем со списком: глубоком этапе рекрусии обрабатываем: (2+0)
// на среднем: 1 * 1 "or вот этой части уравнения "( ( 2 + 0 ) * 1 ) "
// Посмтортите сами
// for (String x : stringList2) System.out.print(x );
// System.out.println();
// наш Double :) Также стоит обратить внимание, что для получения класса обертки мы используем не
// Double.parseDouble() а Double.valueOf()
Double result = 0d;
// Сами алгоритмы вычеслений, впринципе понятны, поэтому не буду их комментировать.
// Однако обратите внимание на очередность, особенно при вычетании (там instead of 1 условия, 3)
// Если что в комментариях под постом немного объясню, если кто-нибудь дочитает до сюда и у него будет желание)
if (stringList2.indexOf("/") != -1) {
int index = stringList2.indexOf("/");
result = Double.valueOf(stringList2.get(index - 1)) / Double.valueOf(stringList2.get(index + 1));
stringList2.add(index - 1, String.valueOf(result));
stringList2.remove(index + 2);
stringList2.remove(index + 1);
stringList2.remove(index);
}
else if (stringList2.indexOf("*") != -1) {
int index = stringList2.indexOf("*");
result = Double.valueOf(stringList2.get(index - 1)) * Double.valueOf(stringList2.get(index + 1));
stringList2.add(index - 1, String.valueOf(result));
stringList2.remove(index + 2);
stringList2.remove(index + 1);
stringList2.remove(index);
}
else if (stringList2.indexOf("-") != -1) {
int index = stringList2.indexOf("-");
int lastIndex = stringList2.lastIndexOf("-");
if (index == 0) {
result = 0.0 - Double.valueOf(stringList2.get(index + 1));
stringList2.add(0, String.valueOf(result));
stringList2.remove(2);
stringList2.remove(1);
}
else if ((lastIndex-2>0) && (stringList2.get(lastIndex-2).equals("-"))){
result = Double.valueOf(stringList2.get(lastIndex + 1)) + Double.valueOf(stringList2.get(lastIndex - 1));
stringList2.add(lastIndex - 1, String.valueOf(result));
stringList2.remove(lastIndex + 2);
stringList2.remove(lastIndex + 1);
stringList2.remove(lastIndex);
}
else {
result = Double.valueOf(stringList2.get(index - 1)) - Double.valueOf(stringList2.get(index + 1));
stringList2.add(index - 1, String.valueOf(result));
stringList2.remove(index + 2);
stringList2.remove(index + 1);
stringList2.remove(index);
}
}
else if (stringList2.indexOf("+") != -1) {
int index = stringList2.indexOf("+");
result = Double.valueOf(stringList2.get(index - 1)) + Double.valueOf(stringList2.get(index + 1));
stringList2.add(index - 1, String.valueOf(result));
stringList2.remove(index + 2);
stringList2.remove(index + 1);
stringList2.remove(index);
}
// Вот тут все немного коряво. (На всякий случий проверял отсутствие (*/+-))
if ((stringList2.indexOf("*") == -1) && (stringList2.indexOf("/") == -1) && (stringList2.indexOf("+") == -1) && (stringList2.indexOf("-") == -1)) {
return result;
}
}
return Double.valueOf(stringList2.get(0));
}
}
</string></string>
感謝所有閱讀並留下評論的人)如果有任何評論,而且很可能有,我會很高興聽到它們)
我之前的文章: |
---|
GO TO FULL VERSION