2013-08-22 12 views
5

Dato un polinomio con una singola variabile x, e il valore di x come input, calcola il suo valore. Esempi:Valuta la stringa polinomiale senza utilizzare regex e API

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

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

Descrizione di emissione: In questo codice che rompono la stringa in una stringa ogni volta che un +/- si incontra e passare la stringa ad una funzione che restituisce singolo termine come "-2x^3". Quindi il mio codice per input = "-2x^3 + 10x-4x^2" calcola solo fino a "-2x^3 + 10x" e salta la parte "-4x^2".

Qualcuno può dirmi cosa c'è di sbagliato qui?

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

Mi permetta di riformulare - Quando si tenta di eseguire il codice di esempio come è, ottengo 'Exception in thread java.lang.NumberFormatException "principale": Per stringa di input: "+10"'. Ciò significa che il tuo esempio di codice non riproduce il problema, il che rende la vita più difficile per noi. – Dukeling

+0

Dukeling ha ragione, perché hai incluso il segno +/- nella stringa dopo averlo trovato. Per evitare ciò, è necessario modificare 'str = str.substring (i);' per essere 'str = str.substring (i + 1);' in questo modo il resto della stringa inizia dopo +/- piuttosto che includere esso. –

+0

Ma non ha bisogno di includerlo se è "-"? Altrimenti il ​​fatto che sia '-' piuttosto che '+' si perde completamente. – ajb

risposta

1

La sostituzione codice dovrebbe aiutare

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

Anche se ci potrebbero essere modi migliori, ma ho voluto solo per mostrare una via qui fuori. Il motivo è che stai cercando + o - come delimitatore. Ma l'ultima parte dell'espressione non finirà con uno di questi, ma solo probabilmente EOL

+0

Il tuo e il suggerimento di @ Dukeling hanno combinato il trucco! Grazie. – abhishek14d

0

La semplice risposta è che quando si esegue questa operazione:

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

l'effetto è che si sta impostando SUBSTR al testo appena prima - o +, e la valutazione di esso. Ma poiché non c'è né - né + alla fine della stringa, non c'è modo in cui questa logica valuterà l'ultimo termine del polinomio, dal momento che valuta solo sottostringhe che sono giuste prima di un - o +.

P.S. Questo è solo un problema che ho notato. Non so se il resto della logica sia corretto.

0

Quando si analizza la stringa, si cerca +/- e si interrompe solo se le si trova. Questo funziona per i primi due termini, ma quando si scende a "-4x^2" il ciclo non si fermerà perché non c'è alcun +/-. Quindi, oltre alle condizioni che hai, devi aggiungere del codice in modo che quando viene raggiunta la fine della stringa, ciò che ti rimane è l'ultimo termine. Allora, cosa si desidera avere questo

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); 
    } 

sarò anche buttare via il disclaimer che ci possono essere più errori, ma questo è l'importante quello che causa il problema.

EDIT: il cambiamento aggiunto else if dichiarazione e il cambiamento aggiunto di cui al mio commento sopra

1
  1. È necessario spiegare l'ultimo termine (il se-dichiarazione attiverà solo quando un - o + viene trovato, che non c'è alla fine).

    Un modo semplice per farlo è quello di sostituire:

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

    con:

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

    È possibile che questo va semplicemente su per un altro iterazione e, su quella iterazione, va sempre in se -statoment, causando l'elaborazione dell'ultimo termine.

  2. È inoltre possibile semplificare

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

    A:

    if (str.charAt(0) != '-') 
    { 
        str = '+' + str; 
    } 
    // common code 
    
  3. C'è anche un bug con la gestione +. Ottengo un NumberFormatException per questo. Un modo per gestire la cosa è di ignorare la + tra i termini (e non l'aggiunta di un + al punto di partenza):

    if (i != len && str.charAt(i) == '+') 
        str = str.substring(i+1); 
    else 
        str = str.substring(i); 
    
  4. e si potrebbe anche fare le funzioni static e chiamarli direttamente piuttosto che dichiarare un nuovo istanza della tua classe.

Test.

+1

In realtà dovrebbe essere (i == len-1) dentro se. Ha funzionato. Grazie! – abhishek14d

+1

@ abhishek14d ['i == len' sembra funzionare bene.] (Https://ideone.com/ikOFlX) Ho apportato alcune aggiunte alla mia risposta. – Dukeling

2

Cosa c'è di sbagliato nell'usare regex? È possibile dividere il polinomio in monomi, valutarli e aggiungere tutti i risultati.

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

Sicuramente il più chiaro (e che è esattamente lo stesso regex che avrei usato), ma il titolo mi fa pensare che è un compito di classe e le regex sono proibite. – ajb

0

con le espressioni regolari, è possibile ottenere una soluzione più semplice. E vuoi supporto per semplici costanti? Prova il prossimo:

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; 
    } 
} 
Problemi correlati