2013-08-22 21 views
5

Biorąc pod uwagę wielomian z pojedynczą zmienną x, a wartość x jako dane wejściowe, oblicz jej wartość. Przykłady:Oceń ciąg wielomianowy bez użycia wyrażenia regularnego i interfejsu API

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

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

Opis problemu: W ten kod przerwać łańcuch w fragmentu ilekroć +/- napotyka i przechodzi podciąg do funkcji, którą ocenia pojedynczego określenia jak „-2x^3”. Tak więc mój kod dla input = "-2x^3 + 10x-4x^2" oblicza tylko do "-2x^3 + 10x" i pomija część "-4x^2".

Czy ktoś może mi powiedzieć, co jest nie tak?

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

Pozwól mi przeformułować - Gdy próbuje uruchomić przykładowy kod jak jest, mam 'Wyjątek w wątku„głównym”java.lang.NumberFormatException: Dla ciągu wejściowego:„+10”'. Oznacza to, że próbka kodu nie powiela problemu, co utrudnia nam życie. – Dukeling

+0

Dukeling ma rację, ponieważ wpisujesz znak +/- w ciąg po znalezieniu go. Aby tego uniknąć, musisz zmienić 'str = str.substring (i);' na 'str = str.substring (i + 1);' w ten sposób reszta łańcucha zaczyna się po +/- zamiast włączania to. –

+0

Ale czy nie musi go dołączyć, jeśli to "-"? W przeciwnym razie fakt, że "-" zamiast "+" zostaje całkowicie utracony. – ajb

Odpowiedz

1

w moim komentarzu Ta wymiana kod powinien pomóc

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

Choć nie mogłyby być lepsze sposoby, ale chciałem tylko pokazać drogę tu. Powód jest taki, że szukasz + lub - jako ogranicznika. ale ostatnia część wypowiedzi nie zakończy się z jednym z nich, ale tylko prawdopodobnie EOL

+0

Twoja sugestia Yours and @ Dukeling w połączeniu sprawdziła się! Dzięki. – abhishek14d

0

Prosta odpowiedź jest taka, że ​​kiedy to zrobić:

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

efektem jest to, że jesteś ustawienie substr do tekstu tylko przed - lub +, a oceniając go. Ale ponieważ nie ma żadnego - lub + na końcu łańcucha, nie ma mowy, aby ta logika oceniała ostatni termin wielomianu, ponieważ ocenia tylko podciągi, które są tuż przed znakiem - lub +.

P.S. To tylko jeden problem, który zauważyłem. Nie wiem, czy reszta logiki jest poprawna.

0

Podczas analizy łańcucha szukamy +/- i zatrzymujemy się tylko, jeśli je znajdziemy. Działa to przez pierwsze dwie kadencje, ale gdy dojdziesz do "-4x^2", pętla się nie zatrzyma, ponieważ nie ma +/-. Zatem oprócz warunków, które posiadasz, musisz dodać kod, aby po osiągnięciu końca łańcucha pozostawało ostatnie słowo. Więc co chcesz mieć to za

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

będę również wyrzucić zastrzeżenie, że nie może być więcej błędów, ale to jest główną przyczyną jeden problem.

EDIT: dodano zmiana else if oświadczeniu i dodała zmiany wspomnianego powyżej

1
  1. Trzeba uwzględnić ostatniej kadencji (if-oświadczenie będzie wywołać tylko wtedy, gdy - lub + zostanie znaleziony, którego nie ma na końcu).

    Prostym sposobem, aby to zrobić, to wymienić:

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

    z:

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

    Powyższy po prostu idzie na jedną więcej iteracji i na tej iteracji, zawsze idzie do if -zakończenie, powodując przetworzenie ostatniego terminu.

  2. Można również uprościć

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

    Do:

    if (str.charAt(0) != '-') 
    { 
        str = '+' + str; 
    } 
    // common code 
    
  3. Jest też błąd z obsługi +. Dostaję do tego NumberFormatException. Jednym ze sposobów, aby poradzić jest ignorowanie + pomiędzy warunkami (a nie dodanie + na początku):

    if (i != len && str.charAt(i) == '+') 
        str = str.substring(i+1); 
    else 
        str = str.substring(i); 
    
  4. I równie dobrze można dokonać funkcje static i nazywają je bezpośrednio zamiast deklarowania nowa instancja twojej klasy.

Test.

+1

Właściwie powinno to być (i == len-1) wewnątrz, jeśli. Zadziałało. Dzięki! – abhishek14d

+1

@ abhishek14d ['i == len' wydaje się działać bez zarzutu.] (Https://ideone.com/ikOFlX) Wprowadziłem kilka poprawek do mojej odpowiedzi. – Dukeling

2

Co jest nie tak z używaniem regex? Możesz podzielić wielomian na monomialny, ocenić każdy i dodać wszystkie wyniki.

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

Zdecydowanie najjaśniejszy (i to dokładnie to samo, co użyłbym regex, którego użyłbym), ale tytuł sprawia, że ​​myślę, że jest to zadanie klasowe, a wyrazy regularne są zabronione. – ajb

0

z wyrażeniami regularnymi, można uzyskać bardziej proste rozwiązanie. Czy chcesz wspierać proste stałe? Spróbuj następny:

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; 
    } 
} 
Powiązane problemy