В этом дополнительном задании Вам предлагается попрактиковаться в написании кода, а также в использовании полиморфизма. Мотивацией к составлению этого доп. задания послужил тот факт, что студенты в первом семестре чаще всего не до конца понимают полиморфизм (а понимать надо).
Вам необходимо разработать "особый" калькулятор, используя скромный шаблон кода, представленный в этом репозитории. Вам не требуется собирать jar-архив, запускать код из консоли и т.д. Проверка функицональности калькулятора осуществляется при помощи авто-тестов, написанных преподавателями.
Вы также можете запустить эти тесты, для этого:
- Откройте терминал вашей ОС
- Перейдите в директорию с проектом (команда
cd
) - Выполните команду:
./gradlew test
Для Windows:
./gradlew.bat test
Система сборки Gradle автоматически запустить весь набор тестов и после их
завершения предоставит отчет о тестировании как в терминале, так и в виде html
документа (см build/reports/tests/test/index.html
), который Вы можете открыть в любом браузере.
Вам необходимо реализовать калькулятор поддерживающий следующие целочисленные операции:
a + b
- сложить числаa
иb
a - b
- вычесть изa
b
a * b
- умножитьa
наb
a \ b
- получить целую часть от деленияa
наb
a % b
- получить остаток от деленияa
наb
a ^ b
- возвестиa
в степеньb
a ++ b
- сложитьa
иb
, затем к результату прибавитьb
a -- b
- вычесть изa
b
, затем из результата вычестьb
a */ b
- умножитьa
наb
, затем получить целую часть от деления результата наb
Приоритеты всех операций равны. Скобки не используются.
Гарантируется, что результат любой из операций находится в пределах от -2^63 - 1
до 2^63
.
Кроме того, в конструкторе калькулятора задается количество ячеек памяти калькулятора (если параметр конструктора отрицательный или больше 100, следует трактовать его как 0). При создании объекта класса калькулятора считается, что все ячейки заполнены нулями. Для работы с ячейками памяти в калькуляторе определены 2 метода:
String putLastResultInMemory(int memoryCellIndex)
- калькулятор должен запомнить результат последней операции в ячейке памяти с индексомmemoryCellIndex
.String resetMemory(int memoryCellIndex)
- калькулятор должен очистить (т.е. записать 0) в ячейку памяти с индексомmemoryCellIndex
.
При вызове любого из вышеперечисленных методов с неправильным параметром, например, отрицательным.
необходимо вернуть строку ERROR_1
. Если же параметр правильный, нужно вернуть обновленное значение
ячейки памяти.
Кроме того, вместо числа в выражении может использоваться Mi
, что означает "использовать
в качестве значения операнда содержимое ячейки памяти с индексом i". Гарантируется, что i
находится в диапазоне от 0 до 100 (включительно обе границы).
Для выполнения самих вычислений в калькуляторе определен метод String calculate(String expression)
.
Он принимает в качестве аргумента строку-выражение, значение которой необходимо вычислить.
Гарантируется, что:
- все числа в строке находятся в диапазоне от
-2^31 - 1
до2^31
. - количество операций в строке не превосходит 5.
- на месте операнда в выражении либо целое число в описанном диапазоне, либо выражение
Mi
. - выражение не начинается и не оканчивается на символ операции.
Если при вычислении выражения случается ошибка, непредвиденная ситуация нужно вернуть одно из сообщений:
- ошибка деления на 0 -
ERROR_0
- ячейка памяти не существует -
ERROR_1
- правый операнд при возведении в степень отрицательный -
ERROR_2
- правый операнд в операции деления с остатком отрицательный -
ERROR_3
Аргумент метода calculate
:
5 + 4 -- 1 * 9
Возвращаемое значение метода calculate
:
63
Пояснение:
Т.к. приоритеты всех операций равны, просто вычисляем слева направо:
5 + 4 = 9
9 - 1 - 1 = 7
7 * 9 = 63
Аргумент метода calculate
:
5 - M0
Возвращаемое значение метода calculate
:
5
Пояснение:
При создании калькулятора во всех ячейках памяти (предполагается, что в примере
в качестве параметра конструктора поступило положительное число) записаны нули.
Поэтому: 5 - 0 = 5
Аргумент метода calculate
:
5 % -2
Возвращаемое значение метода calculate
:
ERROR_3
Аргумент метода calculate
:
5 ^ -2
Возвращаемое значение метода calculate
:
ERROR_2
Аргумент метода calculate
:
5 + M5
Возвращаемое значение метода calculate
:
ERROR_1
Пояснение:
В примере считается, что при создании калькулятора в конструктор было передано
значение 5.
Аргумент метода calculate
:
5 \ 0
Возвращаемое значение метода calculate
:
ERROR_0
Аргумент метода calculate
:
5 % 0
Возвращаемое значение метода calculate
:
ERROR_0
Пример кода:
var calculator = new SpecialCalculator(2);
calculator.calculate("2 * 6");
calculator.putLastResultInMemory(0);
calculator.calculate("6 / 4");
calculator.putLastResultInMemory(1);
calculator.calculate("M0 + M1");
Возвращаемое значение при последнем вызове метода calculate
:
13
Пояснение:
По номерам строк:
- Создаем объект калькулятора с двумя ячейками памяти.
- Вычисляем
2 * 6
, результат равен12
. - Запоминаем результат последней операции, т.е.
12
, в ячейку памятиM0
. - Вычисляем
6 / 4
, результат равен1
. - Запоминаем результат последней операции, т.е.
1
, в ячейку памятиM1
. - Вычисляем
M0 + M1
, т.е.12 + 1
, результат равен13
В директории src/main/java
Вы найдете пакет org.itmo.calculator
с единственным
классом в нем - SpecialCalculator
. Вам необходимо дописать в этом пакете свои классы
(любые на Ваше усмотрение) и реализовать пустые методы и конструктор. Сигнатуры методов
уже определены преподавателями.
ЗАПРЕЩАЕТСЯ:
- Менять сигнатуру методов.
- Менять параметры конструктора или определять новые конструкторы.
- Менять модификаторы конструктора и класса.
- Изменять название класса
SpecialCalculator
- Изменять название иерархии пакетов
org.itmo.calculator
- Изменять содержимое директории
src/main
- Изменять содержимое файлов:
.gitignore
build.gradle
gradlew
gradlew.bat
README.md
settings.gradle
РАЗРЕШАЕТСЯ:
- Дополнять код внутри методов.
- Дополнять код внутри конструктора.
- Определять поля класса.
- Определять новые методы класса.
- Определять новые статические методы.
- Создавать новые классы.
- Создавать новые пакеты внутри пакета
org.itmo.calculator
- Оформление в соответствии с Соглашением об именовании (CamelCase)
- Отсутствие длинных цепочек if-ов или гигантских switch-ей. Суть задания не только в реализации корректно работающего кода, но и в изучении полиморфизма. Заменяйте, где это возможно, if-ы, switch-и на полиморфизм.
- Названия ВСЕГО должны быть осмысленными.
- Не должно быть длинных и запутанных методов. Старайтесь использовать маленькие по количеству строк методы.