2013-08-22 2 views
5

Для вычисления полинома с одной переменной x и значения x в качестве значения, вычислите его значение. Примеры:Оценить полиномиальную строку без использования регулярных выражений и API

eval("-2x^3+10x-4x^2","3")=-60 

eval("x^3+x^2+x","6")=258 

Описание вопроса: В этом коде я нарушу строку в подстроки всякий раз, когда +/- встречается и передать подстроку функции, оценивающей единый термин, как «-2X^3». Таким образом, мой код для ввода = «-2x^3 + 10x-4x^2» вычисляет только до «-2x^3 + 10x» и пропускает часть «-4x^2».

Может кто-нибудь, пожалуйста, скажите мне, что здесь не так?

public class EvalPolyX2 { 

    static String testcase1 = "-2x^3+10x-4x^2"; 
    static String testcase2 = "3"; 

    public static void main(String args[]){ 
     EvalPolyX2 testInstance = new EvalPolyX2(); 
     int result = testInstance.eval(testcase1,testcase2); 
     System.out.println("Result : "+result); 
    } 

    public int eval(String str,String valx){ 

     int sum = 0;   
     String subStr = ""; 
     if(str.charAt(0) == '-') 
     { 
      int len = str.length(); 
      for (int i = 0; i < len; i++) 
      { 
       if(str.charAt(i) == '-' || str.charAt(i) == '+') 
       {     
        subStr = str.substring(0, i); 
        System.out.println("subStr="+subStr); 
        sum += evalSubPoly(subStr, valx); 
        str = str.substring(i); 
        len = str.length(); 
        i = 0; 
       }    
      } 
     } 
     else if(str.charAt(0) != '-') 
     { 
      str = '+' + str; 
      int len = str.length(); 
      for (int i = 0; i < len; i++) 
      { 
       if(str.charAt(i) == '-' || str.charAt(i) == '+') 
       { 
        subStr = str.substring(0, i); 
        System.out.println("subStr="+subStr); 
        sum += evalSubPoly(subStr, valx); 
        str = str.substring(i); 
        len = str.length(); 
        i=0; 
       } 
      } 
     } 
     return sum; 
    } 

    public int evalSubPoly(String poly,String valx){ 
     int len = poly.length(); 
     String num = ""; 
     String power = ""; 
     int exp = 0, coeff = 0; 

     for(int i = 0; i < len; i++) 
     { 
      if(poly.charAt(i) == 'x') 
      { 
       num = poly.substring(0, i); 
       coeff = Integer.parseInt(num);        
      } 
      if(poly.charAt(i) == '^') 
      { 
       power = poly.substring(i+1, len); 
       exp = Integer.parseInt(power); 
      }      
     } 

     if(power.equals("")) 
      exp = 1; 
     System.out.println("coeff="+coeff); 

     int sum = 1; 
     int x = Integer.parseInt(valx); 

     for (int i = 0; i < exp; i++) 
     { 
      sum = sum*x; 
     } 
     System.out.println("sum="+sum); 
     sum = sum*coeff; 

     return sum; 
    } 
} 
+0

Позвольте мне перефразировать - При попытке запустить пример кода, как это, я получаю 'Исключение в нити«основной»java.lang.NumberFormatException: Для ввода строки:«+10»'. Это означает, что ваш образец кода не воспроизводит проблему, что затрудняет жизнь для нас. – Dukeling

+0

Dukeling прав, потому что вы указали знак +/- в строке после того, как нашли его. Чтобы избежать этого, вам нужно изменить 'str = str.substring (i);' to be 'str = str.substring (i + 1);' таким образом остальная часть строки начинается после +/-, а не включает Это. –

+0

Но разве он не должен включать его, если это «-»? В противном случае полностью теряется тот факт, что он «-», а не «+». – ajb

ответ

1

Этой замена коды должна помочь

if(str.charAt(i) == '-' || str.charAt(i) == '+' || i == (len - 1)) 
    { 
    if(i == len - 1) 
    { 
    i++; 
    } 
    ... 

Хотя может быть более эффективными способами, но я только хотел показать путь прочь. Причина в том, что вы ищете + или - как разделитель. Но последняя часть выражения не закончится ни с одним из них, но только, вероятно, EOL

+0

Ваши предложения и @ Dukeling в сочетании сделали трюк! Благодарю. – abhishek14d

0

Простой ответ заключается в том, что когда вы делаете это:

  if(str.charAt(i) == '-' || str.charAt(i) == '+') 
      { 
       subStr = str.substring(0, i); 

эффект является то, что вы устанавливаете SubStr в текст только перед тем - или +, и его оценки. Но поскольку в конце строки нет или - + +, эта логика не будет оценивать последний член полинома, поскольку она оценивает только подстроки, которые находятся непосредственно перед a - или +.

P.S. Это только одна проблема, которую я заметил. Я не знаю, правильна ли остальная логика.

0

Когда вы разбираете строку, вы ищете +/- и останавливаетесь, только если найдете их. Это работает для первых двух терминов, но когда вы переходите к «-4x^2», цикл не останавливается, потому что нет +/-. Таким образом, помимо условий, которые у вас есть, вам нужно добавить код, чтобы при достижении конца строки остался последний термин. Так что вы хотите, чтобы это

if(str.charAt(0) == '-') 
    { 
     int len = str.length(); 
     for (int i = 0; i < len; i++) 
     { 
      if(str.charAt(i) == '-' || str.charAt(i) == '+') 
      {     
       subStr = str.substring(0, i); 
       System.out.println("subStr="+subStr); 
       sum += evalSubPoly(subStr, valx); 
       str = str.substring(i+1); 
       len = str.length(); 
       i = 0; 
      }    
     } 
     System.out.println("subStr="+str); 
     sum += evalSubPoly(str, valx); 
    } 


    else if(str.charAt(0) != '-') 
    { 
     str = '+' + str; 
     int len = str.length(); 
     for (int i = 0; i < len; i++) 
     { 
      if(str.charAt(i) == '-' || str.charAt(i) == '+') 
      { 
       subStr = str.substring(0, i); 
       System.out.println("subStr="+subStr); 
       sum += evalSubPoly(subStr, valx); 
       str = str.substring(i+1); 
       len = str.length(); 
       i=0; 
      } 
     } 
     System.out.println("subStr="+str); 
     sum += evalSubPoly(str, valx); 
    } 

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

EDIT: добавлено изменение else if высказывания и добавили изменения упомянутого в моем комментарии выше

1
  1. Вы должны учитывать последний член (если-оператор будет срабатывать только когда - или + найден, которого нет в конце).

    Один простой способ сделать это, чтобы заменить:

    for (int i = 0; i < len; i++) 
    { 
        if (str.charAt(i) == '-' || str.charAt(i) == '+') 
    

    с:

    //     v one more iteration 
    for (int i = 0; i <= len; i++) 
    { 
        if (i == len || str.charAt(i) == '-' || str.charAt(i) == '+') 
    //  \------/ 
    // extra condition 
    

    выше просто продолжается в течение более одной итерации и на этой итерации, всегда переходит в КРП -statement, в результате чего обрабатывается последний термин.

  2. Вы также можете упростить

    if (str.charAt(0) == '-') 
    { 
        // common code 
    } 
    else if (str.charAt(0) != '-') 
    { 
        str = '+' + str; 
        // common code 
    } 
    

    To:

    if (str.charAt(0) != '-') 
    { 
        str = '+' + str; 
    } 
    // common code 
    
  3. Там также ошибка с обработкой +. Для этого я получаю NumberFormatException. Один из способов справиться с этим, чтобы игнорировать + между терминами (и не добавляя + к началу):

    if (i != len && str.charAt(i) == '+') 
        str = str.substring(i+1); 
    else 
        str = str.substring(i); 
    
  4. И вы можете также сделать ваши функции static и вызывать их напрямую, а не объявить новый экземпляр вашего класса.

Test.

+1

На самом деле это должно быть (i == len-1) внутри if. Это сработало. Благодаря! – abhishek14d

+1

@ abhishek14d ['i == len', похоже, работает нормально.] (Https://ideone.com/ikOFlX) Сделал некоторые дополнения к моему ответу. – Dukeling

2

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

private static final Pattern monomial = Pattern 
     .compile("([+-])?(\\d+)?x(?:\\^(\\d+))?"); 

public static int eval(String str, String valx) { 
    Matcher m = monomial.matcher(str); 
    int x = Integer.parseInt(valx); 

    int total = 0; 
    while (m.find()) { 
     String mul = m.group(2); 
     int value = (mul == null) ? 1 : Integer.parseInt(m.group(2)); 

     String pow = m.group(3); 
     value *= (pow == null) ? x : (int) Math.pow(x, 
       Integer.parseInt(pow)); 

     if ("-".equals(m.group(1))) 
      value = -value; 

     total += value; 
    } 

    return total; 
} 

System.out.println(eval("-2x^3+10x-4x^2", "3")); 
System.out.println(eval("x^3+x^2+x", "6")); 
 
-60 
258 
+0

Определенно самое ясное (и это то же самое регулярное выражение, которое я бы использовал), но название заставляет меня думать, что это назначение класса, а регулярные выражения запрещены. – ajb

0

С помощью регулярных выражений, вы можете получить более простое решение. И вам нужна поддержка простых констант? Попробуйте следующее:

public class EvalPolyX2 { 
    public static void main(String args[]) { 
     System.out.println("Result: " + eval("x^3+x^2+x", 6)); 
    } 
    public static int eval(String eq, int val) { 
     int result = 0; 
     String mons[] = eq.split("(?=[+-])(?!\\B)"); 
     for (String str : mons) { 
      str = str.replace("+", ""); 
      if (str.contains("x")) { 
       double a = 1, b = 1; 
       String[] comps = str.split("x\\^?"); 
       if (comps.length > 0) { 
        a = comps[0].isEmpty() ? 1 : Integer.parseInt(comps[0]); 
       } 
       if (comps.length > 1) { 
        b = Integer.parseInt(comps[1]); 
       } 
       result += a * Math.pow(val, b); 
      } else { 
       result += Integer.parseInt(str); 
      } 
     } 
     return result; 
    } 
} 
Смежные вопросы