Код java для калькулятора

SunDrop / Calc.java

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters

package calc ;
import java . io .*;
import java . util .*;
public class Calc
public static void main ( String [] args ) throws Exception
BufferedReader d = new BufferedReader ( new InputStreamReader ( System . in ));
String sIn ;
try
System . out . println ( «Введте выражение для расчета. Поддерживаются цифры, операции +,-,*,/,^,% и приоритеты в виде скобок ( и ):» );
sIn = d . readLine ();
sIn = opn ( sIn );
System . out . println ( calculate ( sIn ));
> catch ( Exception e )
System . out . println ( e . getMessage ());
>
>
/**
* Преобразовать строку в обратную польскую нотацию
* @param sIn Входная строка
* @return Выходная строка в обратной польской нотации
*/
private static String opn ( String sIn ) throws Exception
StringBuilder sbStack = new StringBuilder ( «» ), sbOut = new StringBuilder ( «» );
char cIn , cTmp ;
for ( int i = 0 ; i < sIn . length (); i ++)
cIn = sIn . charAt ( i );
if ( isOp ( cIn ))
while ( sbStack . length () > 0 )
cTmp = sbStack . substring ( sbStack . length ()- 1 ). charAt ( 0 );
if ( isOp ( cTmp ) && ( opPrior ( cIn ) <= opPrior ( cTmp )))
sbOut . append ( » » ). append ( cTmp ). append ( » » );
sbStack . setLength ( sbStack . length ()- 1 );
> else
sbOut . append ( » » );
break ;
>
>
sbOut . append ( » » );
sbStack . append ( cIn );
> else if ( ‘(‘ == cIn )
sbStack . append ( cIn );
> else if ( ‘)’ == cIn )
cTmp = sbStack . substring ( sbStack . length ()- 1 ). charAt ( 0 );
while ( ‘(‘ != cTmp )
if ( sbStack . length () < 1 )
throw new Exception ( «Ошибка разбора скобок. Проверьте правильность выражения.» );
>
sbOut . append ( » » ). append ( cTmp );
sbStack . setLength ( sbStack . length ()- 1 );
cTmp = sbStack . substring ( sbStack . length ()- 1 ). charAt ( 0 );
>
sbStack . setLength ( sbStack . length ()- 1 );
> else
// Если символ не оператор — добавляем в выходную последовательность
sbOut . append ( cIn );
>
>
// Если в стеке остались операторы, добавляем их в входную строку
while ( sbStack . length () > 0 )
sbOut . append ( » » ). append ( sbStack . substring ( sbStack . length ()- 1 ));
sbStack . setLength ( sbStack . length ()- 1 );
>
return sbOut . toString ();
>
/**
* Функция проверяет, является ли текущий символ оператором
*/
private static boolean isOp ( char c )
switch ( c )
case ‘-‘ :
case ‘+’ :
case ‘*’ :
case ‘/’ :
case ‘^’ :
return true ;
>
return false ;
>
/**
* Возвращает приоритет операции
* @param op char
* @return byte
*/
private static byte opPrior ( char op )
switch ( op )
case ‘^’ :
return 3 ;
case ‘*’ :
case ‘/’ :
case ‘%’ :
return 2 ;
>
return 1 ; // Тут остается + и —
>
/**
* Считает выражение, записанное в обратной польской нотации
* @param sIn
* @return double result
*/
private static double calculate ( String sIn ) throws Exception
double dA = 0 , dB = 0 ;
String sTmp ;
Deque < Double >stack = new ArrayDeque < Double >();
StringTokenizer st = new StringTokenizer ( sIn );
while ( st . hasMoreTokens ())
try
sTmp = st . nextToken (). trim ();
if ( 1 == sTmp . length () && isOp ( sTmp . charAt ( 0 )))
if ( stack . size () < 2 )
throw new Exception ( «Неверное количество данных в стеке для операции » + sTmp );
>
dB = stack . pop ();
dA = stack . pop ();
switch ( sTmp . charAt ( 0 ))
case ‘+’ :
dA += dB ;
break ;
case ‘-‘ :
dA -= dB ;
break ;
case ‘/’ :
dA /= dB ;
break ;
case ‘*’ :
dA *= dB ;
break ;
case ‘%’ :
dA %= dB ;
break ;
case ‘^’ :
dA = Math . pow ( dA , dB );
break ;
default :
throw new Exception ( «Недопустимая операция » + sTmp );
>
stack . push ( dA );
> else
dA = Double . parseDouble ( sTmp );
stack . push ( dA );
>
> catch ( Exception e )
throw new Exception ( «Недопустимый символ в выражении» );
>
>
if ( stack . size () > 1 )
throw new Exception ( «Количество операторов не соответствует количеству операндов» );
>
return stack . pop ();
>
>

Источник

Консольный калькулятор Java

Необходимо написать простой консольный калькулятор на Java.

  • Метод int getInt() — должен считывать с консоли целое число и возвращать его
  • Метод char getOperation() — должен считывать с консоли какое-то значение и возвращать символ с операцией (+, -, * или /)
  • Метод int calc(int num1, int num2, char operation) — должен выполнять над числами num1 и num2 арифметическую операцию, заданную operation.
  • Метод main() — должен считывать 2 числа (с помощью getInt()), считать операцию (с помощью getOperation(), передать все методу calc() и вывести на экран результат.

Решение:

Комментарии к задаче:

Прежде чем решать данную задачу, необходимо разбить задачу на подзадачи. Как видно из картинки ниже, всего есть 3 основных шага:

Поэтому в методе int getInt() мы прописали механику считывания числа с консоли и проверки целочисленное число введено или нет.

  • И потом просто в методе main() вызовем 2 раза метод int getInt(), потому что пользователь будет вводить 2 числа.
  • Обратите внимание, что с помощью конструкции if-else мы прописали, что если число целочисленное, тогда присвоить введенное пользователем значение в переменную num, если же не целочисленное, — вывести в консоль «Вы допустили ошибку при вводе числа. Попробуйте еще раз».
  • Также обратите внимание, что мы использовали рекурсию в else:

Выбор операции (+,-,*,/) мы осуществили с помощью метода char getOperation()

Как видите, пользователю предлагается ввести операцию. А далее программа должна распознать было ли введенное пользователем значение типа char или нет. Причем нас устроит только, если пользователь введет: +, — , * или /. Например, если пользователь введет число, нас не устроит. Верно? Поэтому мы применили небольшую «хитрость» вот в этих 2 строчках кода:

Мы с помощью метода сканера next() считали всю строчку. А далее, поскольку нам не нужна вся строка, а нужен только первый элемент строки, то есть нулевой элемент, поэтому мы вызвали еще и метод charAt(0). И таким образом мы получим только значение 0-го элемента, а не всей строки.

Если вдруг подзабыли как работают методы сканера, перечитайте еще раз вот эту статью — «Работа со сканером в Java». А также, если необходимо вспомнить как работает метод charAt(), перечитайте вот эту статью — «charAt() в Java»

И далее мы прописали сам метод int calc(int num1, int num2, int operation):

Как видите, мы использовали конструкцию switch-case. И прописали, что:

  • если пользователь ввел +, тогда num1+num2, то есть суммируем 2 числа, введенных пользователем.
  • если пользователь ввел -, тогда num1-num2, то есть из 1-го числа, введенного пользователем вычитаем 2-е число
  • и т.д.

Если вдруг Вам необходимо вспомнить как работает конструкция switch-case, перечитайте вот эту статью — «Условный оператор if в Java. Оператор switch»

Также обратите внимание, что здесь мы тоже использовали рекурсию. Вот в этих строчках кода:

И после того как мы прописали все необходимы методы, мы в методе main() прописали следующее:

  • То есть в переменные num1 и num2 будут присвоены, соответственно, 1-е и 2-е число, введенное пользователем.
  • В переменную operation будет присвоена операция, которую ввел пользователь: +, — , * или /
  • Далее в переменную result будет присвоен результат вычислений «нашего калькулятора»
  • И после этого результат будет выведен в консоль

Надеемся — наша статья была Вам полезна. Есть возможность записаться на наши курсы по Java. Детальную информацию смотрите у нас на сайте.

Источник

Калькулятор на Java с базой лишь в 10 лвл JavaRush (3Kyu задача на CodeWars)

Java-университет

Калькулятор на Java с базой лишь в 10 лвл JavaRush (3Kyu задача на CodeWars) - 1

Очередная статья про мои приключения на CodeWars. На этот реализуем функционал элементарного калькулятора: Create a simple calculator that given a string of operators (), +, -, *, /. У меня за плечами лишь 10+ уровней JavaRush, поэтому код довольно громоздок, но функционирует отлично. Задача как вы могли заметить, с сайта CodeWars . Ее ранг — 3kyu . ссылку могу дать в личке. Вот частичный список методов и процессов, которые мне помогли:

  1. Рекурсия. Процесс, при котором метод вызывает сам себя (впервые его применил:)), в данном случае необходима, чтобы избавиться от скобок.
  2. Методы String ‘a trim() , split() , substring() , replace() .
  3. Базовые методы коллекции List .
  4. А также преобразование типов 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(), чтобы избавиться от пробелов по краям. // Обратите внимание, что каждым вторым элиментом я добавляю " ". Для того, чтобы потом мне было легче работать со строкой ListstrList = 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(); // После того, как дочитаете код до конца, расскоментируйте две верхние строчки // и посмотрите как работает рекрусия // Этап 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 элемента String test = expression.substring(expression.indexOf("("), expression.lastIndexOf(")") + 1); // test - последовательность как и сверху, но с добавлением скобок по краям // т.к. наш метод evaluate() возвращает Double, мы должны преобразовать результат рекрусии в String; String testRecursion = String.valueOf(evaluate(recursion)); expression = expression.replace(test, testRecursion); // преобразовали нашу строку с использование рекруси. Избавились от первых скобок 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(" "); >// Тут повторили тот же алгоритм, что и в первой конструкции > > > // Этап 3 // Заключительный этап на котором мы будем реализовывать сами вычесления (*/-+) // Всю реализацию помещаем в цикл while ( который прекратиться, если все действия будут выполнены (соответственно в списке останется 1 элемент)). // Внимательно посмотрите на порядок операций: 1)/ 2)* 3)- 4)+ // System.out.println(expression + "-------expression-"); // System.out.println(); // создаем очередной список для реализации вычеслений, на этот раз без добавления " ". List stringList2 = new ArrayList<>(); for (String element : expression.trim().split(" ")) < stringList2.add(element); >while (stringList2.size() != 0) < // работаем со списком: глубоком этапе рекрусии обрабатываем: (2+0) // на среднем: 1 * 1 "или вот этой части уравнения "( ( 2 + 0 ) * 1 ) " // Посмтортите сами // for (String x : stringList2) System.out.print(x ); // System.out.println(); // наш Double :) Также стоит обратить внимание, что для получения класса обертки мы используем не // Double.parseDouble() а Double.valueOf() Double result = 0d; // Сами алгоритмы вычеслений, впринципе понятны, поэтому не буду их комментировать. // Однако обратите внимание на очередность, особенно при вычетании (там вместо 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)); > > 

Спасибо всем кто прочитал и оставил комментарий) Если есть замечания, а скорее всего они есть, буду рад услышать их)

Источник

Читайте также:  Time server using java
Оцените статью