Domanda Risolvere espressioni matematiche

Stato
Discussione chiusa ad ulteriori risposte.
[MENTION=156155]St3ve[/MENTION]
Sai quando ho detto "risolvere" le parentesi?
Intendevo questo

PHP:
#include<iostream>
#include<string>
#include<vector>

using namespace std;

int conv_str(string);
float resolve_cast(string);

int main()
{/////////////////////////////////////////////////////////////////
  string espressione;
  float risultato;
  
  cout<<"inserisci espressione: "; cin>>espressione;
  
  risultato=resolve_cast(espressione);
  
  cout<<risultato<<endl;
}////////////////////////////////////////////////////////////////

float resolve_cast(string esp)
{
  string tmp=esp;
  vector<char> op;
  vector<int> vals;
  float ris;
  int plus=0;
  
  for(int i=0; i<esp.size(); i++)
    {
      if(esp[i]=='+' || esp[i]=='-' || esp[i]=='*' || esp[i]=='/')
      op.push_back(esp[i]);
    }
  
  if(op[0]=='+' || op[0]=='-')
  {
    
    op.resize(0);
    
    for(int i=0; i<tmp.size(); i++)
    {
      if(tmp[i]=='+' || tmp[i]=='-') 
      {
    vals.push_back(conv_str(tmp.substr(0, i)));
    tmp=tmp.substr(i+1, (tmp.size()-1));
    i=0; 
      }
    }

    vals.push_back(conv_str(tmp)); 

    for(int i=0; i<esp.size(); i++)
    {
      if(esp[i]=='+' || esp[i]=='-')
    op.push_back(esp[i]);
    }

    if(op[0]=='+')
      ris=vals[0]+vals[1];
    else if(op[0]=='-')
      ris=vals[0]-vals[1];

    if(vals.size()==2)
      return ris;


    for(int i=1; i<op.size(); i++)
    {
      if(op[i]=='+')
    ris=ris+vals[i+1];
      else if(op[i]=='-')
    ris=ris-vals[i+1];
    }

    return ris; 
  }
  
  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  else if(op[0]=='*' || op[0]=='/')
  {
    
    op.resize(0);
    
    for(int i=0; i<tmp.size(); i++)
    {
      if(tmp[i]=='*' || tmp[i]=='/') 
      {
    vals.push_back(conv_str(tmp.substr(0, i)));
    tmp=tmp.substr(i+1, (tmp.size()-1));
    i=0; 
      }
    }
    
    vals.push_back(conv_str(tmp)); 

    for(int i=0; i<esp.size(); i++)
    {
      if(esp[i]=='*' || esp[i]=='/')
    op.push_back(esp[i]);
    }

    if(op[0]=='*')
      ris=vals[0]*vals[1];
    else if(op[0]=='/')
      ris=vals[0]/vals[1];
    
    if(vals.size()==2)
      return ris;
    
    for(int i=1; i<op.size(); i++)
    {
      if(op[i]=='*')
    ris=ris*vals[i+1];
      else if(op[i]=='/')
    ris=ris/vals[i+1];
    }
    
    return ris;
  }
} 


int conv_str(string s)
{
  int num = 0;
  
    for(size_t it = 0; it < s.length(); it++) 
    {
      num *= 10;   
      num += s[it] - '0'; 
    } 
    
  return num;
}

Poi è chiaro che è da migliorare, ma è la mia versione! Credo che il grosso del lavoro stesse qui!
Non è il solver ma sono UNA PARTE, cioè la parte di codice che si occupa di lavorare sulla singola parentesi contenenti iperazioni di pari priorità! Che ne dici?

- - - Updated - - -

forse dovrei rendere resolve_cast() una parametrica (?)
 
  • Mi piace
Reazioni: St3ve
@St3ve
Sai quando ho detto "risolvere" le parentesi?
Intendevo questo

PHP:
#include<iostream>
#include<string>
#include<vector>

using namespace std;

int conv_str(string);
float resolve_cast(string);

int main()
{/////////////////////////////////////////////////////////////////
  string espressione;
  float risultato;
  
  cout<<"inserisci espressione: "; cin>>espressione;
  
  risultato=resolve_cast(espressione);
  
  cout<<risultato<<endl;
}////////////////////////////////////////////////////////////////

float resolve_cast(string esp)
{
  string tmp=esp;
  vector<char> op;
  vector<int> vals;
  float ris;
  int plus=0;
  
  for(int i=0; i<esp.size(); i++)
    {
      if(esp[i]=='+' || esp[i]=='-' || esp[i]=='*' || esp[i]=='/')
      op.push_back(esp[i]);
    }
  
  if(op[0]=='+' || op[0]=='-')
  {
    
    op.resize(0);
    
    for(int i=0; i<tmp.size(); i++)
    {
      if(tmp[i]=='+' || tmp[i]=='-') 
      {
    vals.push_back(conv_str(tmp.substr(0, i)));
    tmp=tmp.substr(i+1, (tmp.size()-1));
    i=0; 
      }
    }

    vals.push_back(conv_str(tmp)); 

    for(int i=0; i<esp.size(); i++)
    {
      if(esp[i]=='+' || esp[i]=='-')
    op.push_back(esp[i]);
    }

    if(op[0]=='+')
      ris=vals[0]+vals[1];
    else if(op[0]=='-')
      ris=vals[0]-vals[1];

    if(vals.size()==2)
      return ris;


    for(int i=1; i<op.size(); i++)
    {
      if(op[i]=='+')
    ris=ris+vals[i+1];
      else if(op[i]=='-')
    ris=ris-vals[i+1];
    }

    return ris; 
  }
  
  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  else if(op[0]=='*' || op[0]=='/')
  {
    
    op.resize(0);
    
    for(int i=0; i<tmp.size(); i++)
    {
      if(tmp[i]=='*' || tmp[i]=='/') 
      {
    vals.push_back(conv_str(tmp.substr(0, i)));
    tmp=tmp.substr(i+1, (tmp.size()-1));
    i=0; 
      }
    }
    
    vals.push_back(conv_str(tmp)); 

    for(int i=0; i<esp.size(); i++)
    {
      if(esp[i]=='*' || esp[i]=='/')
    op.push_back(esp[i]);
    }

    if(op[0]=='*')
      ris=vals[0]*vals[1];
    else if(op[0]=='/')
      ris=vals[0]/vals[1];
    
    if(vals.size()==2)
      return ris;
    
    for(int i=1; i<op.size(); i++)
    {
      if(op[i]=='*')
    ris=ris*vals[i+1];
      else if(op[i]=='/')
    ris=ris/vals[i+1];
    }
    
    return ris;
  }
} 


int conv_str(string s)
{
  int num = 0;
  
    for(size_t it = 0; it < s.length(); it++) 
    {
      num *= 10;   
      num += s[it] - '0'; 
    } 
    
  return num;
}

Poi è chiaro che è da migliorare, ma è la mia versione! Credo che il grosso del lavoro stesse qui!
Non è il solver ma sono UNA PARTE, cioè la parte di codice che si occupa di lavorare sulla singola parentesi contenenti iperazioni di pari priorità! Che ne dici?

- - - Updated - - -

forse dovrei rendere resolve_cast() una parametrica (?)

Per dividere i numeri dai simboli basta una cosa di questo tipo (testata):
Codice:
int main()
{
    string expression;

    cout << "inserisci espressione: ";
    cin >> expression;

    vector<int> numeri;
    vector<char> simboli;
    for(size_t pos = 0; pos < expression.size(); pos++)
    {
        numeri.push_back(str_to_int(expression, pos));
        simboli.push_back(expression[pos]);
    }
    
    // adesso numeri contiene tutti i numeri e simboli contiene tutti i simboli
    
    return 0;
}


int str_to_int(const string &s, size_t &pos)
{
    int num = 0;
  
    for(; s[pos] >= '0' && s[pos] <= '9'; pos++) 
    {
        num *= 10;   
        num += s[pos] - '0'; 
    } 
    
    return num;
}

Nel tuo codice ci sono un po' di cose che non mi tornano, tipo op.resize(0). Secondo me ti conviene strutturarlo meglio: funzioni piccole che facciano una cosa sola (volendo potresti anche andare di oop), tu hai una funzione che fa tutto.
Alla fine per risolverlo io ho usato un algoritmo ricorsivo che si è rilevato corto e molto efficace (e facilmente estendibile), quando consegnerò il progetto faro un post per spiegare bene tutto. Però se vuoi un metodo più intuitivo, che si basa sul dividere i numeri dalle operazioni esattamente come stai facendo, prova a vedere l'algoritmo che avevo postato qualche post fa (in questo caso std::stack è più comodo di std::vector).


PS. Sono a buon punto anche con l'assembly.
 
  • Mi piace
Reazioni: Simur Birkoff
[MENTION=156155]St3ve[/MENTION]
Bene! Accetto il tuo feedback molto volentieri! Ho trovato qualcosa di interessante anche nelle nuove librerie C++11.
Il codice è un po confuso lo ammetto. Forse devo rivedere un paio di cosette!
Conosci al volo una funzione di conversione float to string?
 
Conosci al volo una funzione di conversione float to string?

Generalmente il modo migliore per fare conversioni stringhe<->numeri è usando le stringstream, ti permettono anche di convertire stringhe in numeri usando simboli a piacere per definire la virgola e puoi fare altre cose carine.
Ma visto che hai citato il C++11 puoi semplicemente fare:
Codice:
string pippo = std::to_string(12.3456);  // funziona anche con tutti gli altri tipi base
 
  • Mi piace
Reazioni: Simur Birkoff
Generalmente il modo migliore per fare conversioni stringhe<->numeri è usando le stringstream, ti permettono anche di convertire stringhe in numeri usando simboli a piacere per definire la virgola e puoi fare altre cose carine.
Ma visto che hai citato il C++11 puoi semplicemente fare:
Codice:
string pippo = std::to_string(12.3456);  // funziona anche con tutti gli altri tipi base
meglio le stringstream! Preferisco compilare in C++ standard! Grazie! Magari se riesco a finire posto la mia versione!
Grazie di tutto e attendiamo novità!
Saluti!
 
E anche la parte in assembly funziona, devo solo sistemare un paio di cosette per rispettare tutte le convenzioni e poi è fatta.

Grazie mille a tutti quanti per il supporto datomi, a tempo debito farò un post per spiegare il funzionamento dell'algoritmo e posterò il codice.

Passo e chiudo :lock:
 
  • Mi piace
Reazioni: SpeedJack
Stato
Discussione chiusa ad ulteriori risposte.