2013-04-11 5 views
0

Я пытаюсь написать программу, которая решает любое уравнение (от простого к сложному) в виде строки, используя Arraylist, чтобы разбить уравнение на отдельные части. Сначала он проверяет скобки, затем переходит в самый глубокий набор скобок, который он может найти, и решает множество операций внутри, начиная с более сильных операторов, а затем переходит. Он продолжает проверять, пока нет скобок, тогда он делает то, что осталось, начиная с более сильных операторов. Ответ, оставшийся в арраисте, остается ответом. Но у меня проблемы. Вот мой код:Строковое уравнение для простых комплексных уравнений

import java.util.ArrayList; 

public class StringEquation 
{ 
    public static void main(String[] args) 
    { 
     String s = "80+5+3*(11%(3*2)-(5+1)+6)-(10+10)+(2*2)*5"; 

     ArrayList<String> equation = new ArrayList<>(); 

     String ns = ""; 

     String b; 

     int nsi; 

     int si; 

     int res = 0; 

     boolean hasParen = false; 

     for(int c=0; c<s.length(); c++) 
     { 
      b = s.substring(c,c+1); 
      if("0".equals(b)||"1".equals(b)||"2".equals(b)||"3".equals(b)||"4".equals(b)||"5".equals(b)||"6".equals(b)||"7".equals(b)||"8".equals(b)||"9".equals(b)) 
      { 
       ns += b; 
       if(c==s.length()-1) 
       { 
        nsi = Integer.parseInt(ns); 
        equation.add(Integer.toString(nsi)); 
       } 
      } 
      else if(("+".equals(b)||"-".equals(b)||"*".equals(b)||"/".equals(b)||"%".equals(b))&&!"".equals(ns)) 
      { 
       nsi = Integer.parseInt(ns); 
       equation.add(Integer.toString(nsi)); 
       equation.add(b); 
       ns = ""; 
      } 
      else if("(".equals(b)) 
      { 
       equation.add(b); 
      } 
      else if (")".equals(b)) 
      { 
       nsi = Integer.parseInt(ns); 
       equation.add(Integer.toString(nsi)); 
       equation.add(b); 
       ns = ""; 
      } 
      else if("+".equals(b)||"-".equals(b)||"*".equals(b)||"/".equals(b)||"%".equals(b)) 
      { 
       equation.add(b); 
      } 
     } 

     while(true) //checks for parentheses 
     { 
      for(int d=0; d<equation.size(); d++) 
      { 
       if("(".equals(equation.get(d))) 
       { 
        hasParen = true; 
       } 

       if(hasParen==true) 
       { 
        while(!")".equals(equation.get(d))) 
        { 
         d++; 
        } 
        while(!"(".equals(equation.get(d))) 
        { 
         d--; 
        } 
        d++; 

        while(!")".equals(equation.get(d+1))) 
        { 
         if("-".equals(equation.get(d))) //checks to see if the String number on the Arraylist is negative 
         { 
          equation.remove(d); 
          si = Integer.parseInt(equation.get(d)); 
          si *= -1; 
         } 
         else 
         { 
          si = Integer.parseInt(equation.get(d)); 
         } 

         switch(equation.get(d+1)) 
         { 
          case "*": si *= Integer.parseInt(equation.get(d+2)); 
          equation.set(d, Integer.toString(si)); 
          equation.remove(d+1); 
          equation.remove(d+2); 
           break; 
          case "/": si /= Integer.parseInt(equation.get(d+2)); 
          equation.set(d, Integer.toString(si)); 
          equation.remove(d+1); 
          equation.remove(d+2); 
           break; 
          case "%": si %= Integer.parseInt(equation.get(d+2)); 
          equation.set(d, Integer.toString(si)); 
          equation.remove(d+1); 
          equation.remove(d+2); 
           break; 
          default: d+=2; 
         } 
        } 

        while(!"(".equals(equation.get(d))) 
        { 
         d--; 
        } 
        d++; 

        while(!")".equals(equation.get(d+1))) 
        { 
         if("-".equals(equation.get(d))) //checks to see if the String number on the Arraylist is negative 
         { 
          equation.remove(d); 
          si = Integer.parseInt(equation.get(d)); 
          si *= -1; 
         } 
         else 
         { 
          si = Integer.parseInt(equation.get(d)); 
         } 

         switch(equation.get(d+1)) 
         { 
          case "+": si += Integer.parseInt(equation.get(d+2)); 
          equation.set(d, Integer.toString(si)); 
          equation.remove(d+1); 
          equation.remove(d+2); 
           break; 
          case "-": si -= Integer.parseInt(equation.get(d+2)); 
          equation.set(d, Integer.toString(si)); 
          equation.remove(d+1); 
          equation.remove(d+2); 
           break; 
         } 
        } 

        if("(".equals(equation.get(d-1))&&")".equals(equation.get(d+1))) 
        { 
         equation.remove(d-1); 
         equation.remove(d+1); 
        } 

        hasParen = false; 

        d = 0; 
       } 
      } 
      break; 
     } 

     for(int e=0; e<equation.size(); e+=2) //does all multiplication, division and modulus first 
     { 
      if("-".equals(equation.get(e))) //checks to see if the String number on the Arraylist is negative 
      { 
       equation.remove(e); 
       si = Integer.parseInt(equation.get(e)); 
       si *= -1; 
      } 
      else 
      { 
       si = Integer.parseInt(equation.get(e)); 
      } 

      switch(equation.get(e+1)) 
      { 
       case "*": si *= Integer.parseInt(equation.get(e+2)); 
       equation.set(e, Integer.toString(si)); 
       equation.remove(e+1); 
       equation.remove(e+2); 
        break; 
       case "/": si /= Integer.parseInt(equation.get(e+2)); 
       equation.set(e, Integer.toString(si)); 
       equation.remove(e+1); 
       equation.remove(e+2); 
        break; 
       case "%": si %= Integer.parseInt(equation.get(e+2)); 
       equation.set(e, Integer.toString(si)); 
       equation.remove(e+1); 
       equation.remove(e+2); 
        break; 
       default: e+=2; 
      } 
     } 

     for(int f=0; f<equation.size(); f+=2) //does the rest (addition and subtraction) 
     { 
      if("-".equals(equation.get(f))) //checks to see if the String number on the Arraylist is negative 
      { 
       equation.remove(f); 
       si = Integer.parseInt(equation.get(f)); 
       si *= -1; 
      } 
      else 
      { 
       si = Integer.parseInt(equation.get(f)); 
      } 

      switch(equation.get(f+1)) 
      { 
       case "+": si += Integer.parseInt(equation.get(f+2)); 
       equation.set(f, Integer.toString(si)); 
       equation.remove(f+1); 
       equation.remove(f+2); 
        break; 
       case "-": si -= Integer.parseInt(equation.get(f+2)); 
       equation.set(f, Integer.toString(si)); 
       equation.remove(f+1); 
       equation.remove(f+2); 
        break; 
      } 
     } 

     System.out.print(equation.get(0)); //Arraylist should only have the answer of the string equation by this point. 

     //The part below was to see if lines 25-59 had obtained the whole equation in seperate parts within the arraylist. 

//  for(int i=0; i<equation.size(); i++) 
//  { 
//   System.out.print(equation.get(i)); 
//  } 
//  System.out.println("\n"); 
    } 
} 

Когда я запускаю это, он дает мне эту ошибку:

Exception in thread "main" java.lang.NumberFormatException: For input string: "(" 
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) 
    at java.lang.Integer.parseInt(Integer.java:481) 
    at java.lang.Integer.parseInt(Integer.java:527) 
    at stringequationfull.StringEquationFull.main(StringEquationFull.java:87) 
Java Result: 1 

Любая помощь?

ответ

0

Смотрите документацию Integer#parseInt:

Throws: NumberFormatException - if the string does not contain a parsable integer.

Сообщение об ошибке вы получаете очень информативен.

Вы пытаетесь разобрать "(", то есть не анализируемое целое число.

Использование отладчика разрешит это для вас менее чем за минуту.

0

Для этого вам действительно нужно использовать синтаксический анализ/лексирование, а затем реализовать решатель уравнений поверх дерева синтаксического анализа.

Вот отправная точка:.. How to write LALR parser for some grammar in Java?

0

Как уже упоминалось вы пытаетесь разобрать «(» как Integer

Но это не ваша главная проблема

Основной проблемой является то, что вам имеют огромный гигантский кусок кода, о котором излишне сложно рассуждать.

Вам нужно преобразовать строку в структуру дерева, а не список массивов, которая позволит вам выполнять вычисления в значительной степени sier и ошибка.

Поскольку ваша проблема проста, я бы не рекомендовал использовать генератор парсера для этой задачи. (занимает слишком много времени). Однако вам по-прежнему необходимо разработать структуру данных в соответствии с вашими требованиями.

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

В общем, вы будете иметь что-то вроде:

Class Statement{} 

class AddStatement extends Statement{ 
    Statement lhs; 
    Statement rhs; 
} 

Class constant extends Statement{ 
    int value; 
} 

вам нужно будет сделать классы для всех операций, которые вы поддерживаете, а затем рекурсивно разобрать вход в эту структуру. Если все сделано правильно, оценка становится простой.

Я не вдаваюсь в детали, потому что в распоряжении имеется достаточное количество ресурсов, доступных в Интернете для руководства.

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

+0

PS это намного проще в функциональных языках, таких как Haskell –