Advertisement
Guest User

Untitled

a guest
Apr 8th, 2020
205
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 13.27 KB | None | 0 0
  1.  
  2. //////////////// КЛАСС MAIN //////////////////////
  3.  
  4. package lab;
  5.  
  6. import java.util.Scanner;
  7.  /*Основной класс программы.*/
  8.  
  9. public class Main {
  10.  
  11.     public static void main(String[] args) {   
  12.         try {
  13.         // Создаётся объект сканнера для считывания переменных.
  14.         Scanner sc = new Scanner(System.in);   
  15.         // Считываем выражение.
  16.         String line = sc.nextLine();   
  17.         // Сохраняем выражение для вывода в конце.
  18.         String lineCopy = new String(line);
  19.         // Добавляем ноль в конец, чтобы избежать ошибок.
  20.         line = line+"+0";
  21.         // Создаём объект калькулятора для подсчёта значения выражения.
  22.         Calculator calc = new Calculator();
  23.         // Заменяем значение всех ф-ций в строке на численные значения.      
  24.         line = calc.countFunctions(line);
  25.         // Подсчитываем значение выражения.
  26.         calc.calculate(line);
  27.         // Выводим значение выражения.
  28.             System.out.println(lineCopy+" = "+calc.popVal());
  29.         } catch (Exception ex)
  30.         {
  31.             // По стечению обстоятельств, ф-ция будет работать всегда
  32.             // если строка введена корректно. В иных случаях
  33.             // она и не должна работать.
  34.             System.out.println("Ошибка при вычислениях/вводе данных. ");
  35.         }
  36.     }
  37.  
  38. }
  39.  
  40.  
  41. //////////////// КЛАСС CUSTOMSTACK //////////////////////
  42.  
  43.  
  44. /* Класс для стека строк. (Понадобится в классе Calculator при подсчёте значений функций.) */
  45.  
  46. package lab;
  47.  
  48. public class CustomStack
  49. {
  50.         String[] stack = new String[200];
  51.         int ptr = 0;
  52.        
  53.         // Добавление элемента в стек.
  54.         public  void push(String par)
  55.          {
  56.              stack[ptr++]=par;
  57.          }
  58.    
  59.         // Ф-ция возвращает элемент с вершины стека. Элемент удаляется из стека.
  60.          public  String pop()
  61.          {
  62.              return stack[--ptr];
  63.          }
  64.  
  65.         // Просмотр элемента в вершине стека.
  66.          public  String peek()
  67.          {
  68.             return stack[ptr-1];
  69.          }  
  70.  
  71.         // Проверка стека на пустоту.
  72.          public  boolean isEmpty()
  73.          {
  74.              return (ptr==0);
  75.          }
  76. }
  77.  
  78.  
  79. //////////////// КЛАСС CALCULATOR //////////////////////
  80.  
  81.  
  82.  
  83. /*Класс содержит основные функции для работы с введённым выражением.*/
  84.  
  85.  
  86. package lab;
  87.  
  88. import java.util.HashMap;
  89. import java.util.Scanner;
  90.  
  91. public class Calculator {
  92.  
  93.  // в HashMap сохраняются значения конкретных переменных.
  94. public static HashMap<String, Double> variables = new HashMap<String, Double>();
  95.  
  96.        String Lex[]; // Массив содержит элементы введённого выражения. Например для выражения
  97.             // "1+10+z" массив будет содержать Lex[0] = "1", Lex[1] = "+", Lex[2]="10", Lex[3]="+", Lex[4] = "z"
  98.        int ptrL; // Указатель для работы с массивом Lex[].
  99.  
  100.        String opStack[]; // Стек для сохранения операторов.
  101.        int ptrOp; // Указатель стека (индекс текущего элемента, с которым работаем.)
  102.  
  103.        String valStack[]; // Стек для подсчёта значений.
  104.        int ptrVal; // Указатель стека значений.
  105.  
  106.     // Функция инициализации стеков.
  107.      public void Init()
  108.      {
  109.          opStack=new String[200];
  110.          ptrOp=0;
  111.          valStack=new String[200];
  112.          ptrVal=0;
  113.      }
  114.  
  115.     // Определение приоритета операций.
  116.      public int Prty(String o)
  117.      {
  118.          int r=-1;
  119.          switch (o)
  120.          {
  121.             case "(":
  122.                 r=0;
  123.                 break;
  124.             case "+":
  125.             case "-":
  126.                 r=1;
  127.                 break;
  128.             case "*":
  129.             case "/":
  130.                 r=2;
  131.                 break;
  132.             case "^":
  133.                 r=3;
  134.          }  
  135.          return r;
  136.      }
  137.  
  138.     // Функция для работы со стеком. Возвращает элемент в "верхушке" стека.
  139.      public  String peekOp()
  140.      {
  141.         return opStack[ptrOp-1];
  142.      }    
  143.  
  144.     // Проверка стека операторов на пустоту.
  145.      public  boolean isEmptyOp()
  146.      {
  147.          return (ptrOp==0);
  148.      }
  149.  
  150.     // Проверка стека значений на пустоту
  151.      public boolean isEmptyVal()
  152.      {
  153.          return (ptrVal==0);
  154.      }
  155.  
  156.     // Поместить в стек операторов значение.
  157.      public void pushOp(String op)
  158.      {
  159.          opStack[ptrOp++]=op;
  160.      }
  161.  
  162.     // Аналогично ф-ции выше
  163.      public void pushVal(String v)
  164.      {
  165.          valStack[ptrVal++]=v;
  166.      }
  167.  
  168.     // Вернуть значение вверху стека и изменить значение указателя.
  169.      public  String popOp()
  170.      {
  171.          return opStack[--ptrOp];
  172.      }
  173.  
  174.      public String popVal()
  175.      {
  176.          return valStack[--ptrVal];
  177.      }
  178.  
  179.     // Ф-ция получает два значения из стека значений и выполняет операцию, полученную из
  180.     // стека операций. Возвращаемое значение заносится обратно в стек значений.
  181.      public void exec()
  182.      {
  183.         double a1,a2,r;
  184.         String v1,v2;
  185.         String op;
  186.  
  187.         v2=popVal();
  188.         v1=popVal();
  189.         op=popOp();
  190.  
  191.         a1=Double.parseDouble(v1);
  192.         a2=Double.parseDouble(v2);
  193.  
  194.         r=0.0;
  195.  
  196.         switch (op)
  197.         {
  198.            case "+":
  199.                 r=a1+a2;
  200.                 break;
  201.            case "-":
  202.                 r=a1-a2;
  203.                 break;
  204.            case "*":
  205.                 r=a1*a2;
  206.                 break;
  207.            case "/":
  208.                 r=a1/a2;
  209.                 break;
  210.            case "^":
  211.                 r=Math.pow(a1,a2);
  212.                 break;
  213.          }
  214.  
  215.          v1=Double.toString(r);
  216.          pushVal(v1);
  217.  
  218.      }
  219.  
  220.     // Основная ф-ция, с которой начинается разбор выражения.
  221.     // Ф-ция инициализирует стеки;
  222.     // с помощью ф-ции parse(String) разбивает её на элементы, которые заносит в массив Lex[]
  223.     // с помощью ф-ции findVariables() ищет переменные и запрашивает их значения
  224.     // после чего в цикле по каждому элементу (элементы = числа, знаки операций
  225.     // и скобки) выражения начинается работа со стеками значений и операторов, в результате которой
  226.     // в стеке значений остаётся численное значение введённого выражения.
  227.      public void calculate(String l)
  228.      {
  229.          int i;
  230.          String curr,top;
  231.  
  232.          Init();
  233.          parse(l);
  234.          findVariables();
  235.  
  236.          for (i=0; i<= ptrL; i++)
  237.          {
  238.              curr=Lex[i];
  239.              switch (curr)
  240.              {  
  241.                 case "(":
  242.                   pushOp(curr);
  243.                   break;
  244.                 case "+":
  245.                 case "-":
  246.                 case "*":
  247.                 case "/":
  248.                 case "^":
  249.                   if (isEmptyOp())
  250.                   {
  251.                      pushOp(curr);
  252.                      break;
  253.                   }          
  254.                   top=peekOp();
  255.                   if (Prty(curr) > Prty(top))
  256.                   {
  257.                      pushOp(curr);
  258.                      break;
  259.                   }          
  260.                   else
  261.                   {
  262.                      exec();
  263.                      pushOp(curr);
  264.                      break;
  265.                   }
  266.                 case ")":
  267.                      while (true)
  268.                      {
  269.                         top=peekOp();
  270.                         if (top.equals("("))
  271.                         {
  272.                            top=popOp();
  273.                            break;                        
  274.                         }        
  275.                         exec();                      
  276.                      }
  277.                      break;                  
  278.                 default:
  279.                      pushVal(curr);
  280.              }    
  281.           }
  282.  
  283.           while (! isEmptyOp())
  284.           {
  285.              exec();
  286.           }            
  287.  
  288.      }
  289.  
  290.     // Функция идёт посимвольно по выражению и разбивает его на элементы, заполняя массив Lex[]
  291.     // элементами являются знаки операций, числа, скобки.
  292.      public  void parse(String formula)
  293.      {
  294.         char s;
  295.         int i;
  296.         String Tmp="";
  297.         Lex=new String[200];
  298.         for (i=0; i<200; i++) Lex[i]="";
  299.         ptrL=0;
  300.         for (i=0; i<formula.length(); i++)
  301.         {
  302.             s=formula.charAt(i);
  303.             switch (s)
  304.             {
  305.               case '+':
  306.               case '-':
  307.               case '*':
  308.               case '^':
  309.               case '/':
  310.               case '(':
  311.               case ')':
  312.                    if (Tmp.length() > 0)
  313.                    {
  314.                       Lex[ptrL++]=Tmp;
  315.                       Tmp="";
  316.                    }
  317.                    Lex[ptrL++]=""+s;
  318.                    break;
  319.               case ' ':
  320.                    break;
  321.               default:
  322.                    Tmp=Tmp+s;
  323.             }
  324.          }
  325.          if (Tmp.length() > 0) Lex[ptrL]=Tmp;
  326.  
  327.       //   for (int j =0; j<formula.length(); j++)
  328.       //     System.out.println(Lex[j]+"\n");
  329.      }      
  330.  
  331.     // Ф-ция проверяет, содержит ли строка какие-либо символы латинского алфавита.
  332.      public  boolean containsChars(String str)
  333.      {
  334.          boolean flag = false;
  335.          for (int i =0; i<str.length(); i++)
  336.          {
  337.              if ((str.charAt(i) >= 'a' && str.charAt(i) <= 'z') || (str.charAt(i) >= 'A' && str.charAt(i) <= 'Z'))
  338.              {
  339.                  flag = true;
  340.              }
  341.          }
  342.          return flag;
  343.      }
  344.  
  345.     // Ф-ция проверяет выражение на наличие переменных.
  346.     // Для этого каждый элемент строки проверяется на наличие букв.
  347.     // если элемент содержит букву, значит является переменной.
  348.     // При обнаружении переменной, ф-ция запрашивает у пользователя её значение.
  349.      public  void findVariables()
  350.      {
  351.          for (int i =0; i<200; i++)
  352.          {
  353.              String lex = Lex[i];
  354.              if (containsChars(lex))
  355.              { 
  356.                  if (variables.containsKey(lex))
  357.                  {
  358.                      Lex[i] = ""+variables.get(lex);
  359.                  } else
  360.                  {
  361.                  Scanner sc = new Scanner(System.in);
  362.                  System.out.print(lex+" >> ");
  363.                  Double value = sc.nextDouble();
  364.                  Lex[i] = ""+value;  
  365.                  variables.put(lex, value);      
  366.                  }
  367.              }
  368.          }
  369.      }
  370.  
  371.    
  372.     // Рекурсивная ф-ция для подсчёта значений найденных функций. (в примере только sin)
  373.     // Алгоритм работы:
  374.     // В строке находится опредление функции, например, "sin("
  375.     // после чего находится скобка, которая её закрывает и выделяется выражение внутри скобки.
  376.     // (т.е. для выражения "1+sin(sin(x)+2)" будет выделено "sin(x)+2")
  377.     // если выражение внутри не содержит ф-ций, то считается его значение, после чего находится значение ф-ции по посчитанному значению.
  378.     // если выражение содержит ф-ции, то алгоритм продолжается рекурсивно, вызовом ф-ции countFuntions от выделенной строки.
  379.      public String countFunctions(String l)
  380.      {           
  381.         while (l.contains("sin("))
  382.         {
  383.             CustomStack st = new CustomStack();
  384.             String newstr = new String(l);
  385.             int ptr = newstr.indexOf("sin(");
  386.             newstr = newstr.substring(ptr+4, newstr.length()); 
  387.             //System.out.println(newstr);      
  388.             int i =0;
  389.             while (i < newstr.length())
  390.             {
  391.                 if (newstr.charAt(i) == '(')
  392.                     st.push("(");
  393.                 if (newstr.charAt(i) == ')')
  394.                 {
  395.                     if (st.isEmpty())
  396.                     {
  397.                         ptr = i;
  398.                         break;
  399.                     }
  400.                     if (st.peek() == "(")
  401.                         st.pop();
  402.                     else
  403.                         {   ptr = i;
  404.                             break;
  405.                         }
  406.                 }
  407.                 i++;
  408.             }                          
  409.             newstr = newstr.substring(0, ptr); 
  410.             String savedStr = new String(newstr);          
  411.         //  System.out.println(newstr+"  saved="+savedStr);
  412.             newstr = countFunctions(newstr);
  413.         //  System.out.println("-> "+newstr);  
  414.             calculate(newstr);
  415.         //  System.out.println("--> "+newstr); 
  416.  
  417.             Double value = Double.parseDouble(popVal());
  418.             value = Math.sin(value);           
  419.             String formattedDouble = String.format("%.4f", value);
  420.             if (value<0) formattedDouble = "0"+formattedDouble;
  421.             formattedDouble = formattedDouble.replaceAll(",", ".");        
  422.             l = l.replace("sin("+savedStr+")", formattedDouble);       
  423.         }
  424.         return l;
  425.      }
  426. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement