Domanda Risolvere espressioni matematiche

Stato
Discussione chiusa ad ulteriori risposte.
Ok, non sapevo di questa cosa in python! In effetti funziona, in C++ il discorso è differente! Non credo che un'operazione del genere sia fattibile... Ovviamente potrei sbagliare. @St3ve

Certo che si può fare, un po' meno pulito rispetto al python, ma il senso è lo stesso:
Codice:
string esp; 
cout<<"espressione = "; 
cin>>esp;

size_t pos = 0;
int i;
while(esp.length())
{
    try
    {
        i = stoi(esp, &pos);
        cout << "e' il numero = " << i << endl;
        esp = esp.substr(pos);
    }
    catch(...)
    {
        cout << "non e' un numero" << endl;
        esp = esp.substr(pos-1);
    }
}
Output:
Codice:
espressione = 12pippo34ciccio56
e' il numero = 12
non e' un numero
non e' un numero
non e' un numero
non e' un numero
non e' un numero
e' il numero = 34
non e' un numero
non e' un numero
non e' un numero
non e' un numero
non e' un numero
non e' un numero
e' il numero = 56


Molto bene! Se hai tutto il sorgente potresti postaro? Se vuoi eh! :)
Visto che è un progetto scolastico, anche se in realtà mi servirebbe solo l'assembly, preferisco non postarlo per adesso. Quando lo consegno rifinisco un po' il sorgente (magari potrei aggiungerci anche le variabili tipo: 7+(i=12*8)+i^2 oppure in un'espressione calcoli una variabile che poi riusi nell'espressione dopo) e lo posto a scopo didattico.
Devo dire che sto progettino, almeno finché sono sul C, mi sta appassionando.
 
Ultima modifica:
@Simur Birkoff
Da quanto ho capito è un po' il concetto che ho cercato di esprimere qui:
Le parentesi pensavo di gestirle in modo ricorsivo: quando trovo una parentesi aperta inizio a contarle (+1 per quelle aperte e -1 per quelle chiuse) e quando torno a 0 riapplico l'algoritmo di risoluzione sulla sottostringa che parte dopo la prima parentesi e termina prima dell'ultima parentesi trovata, che sarebbe quella che effettivamente chiude la prima parentesi aperta.
Ovviamente per semplificare sto dando per scontato che la stringa in input sia corretta.

Che codato diventa una roba di questo tipo:
Codice:
if(expression[it] == '(')
{
    ++brackets;                                          // inizialmente brackets = 0, trovo una parentesi e diventa 1
    for(it2 = it+1; it < strlen(expression); ++it2)      // it indica la posizione della stringa in cui ho incontrato il carattere '('
    {
        if(expression[it2] == '(')                       // se si apre un'altra parentesi, me lo segno
            ++brackets;
        else if(expression[it2] == ')')                  // se si chiude una parentesi, me lo segno
            --brackets;

        if(brackets == 0)                                // se la parentesi che si è chiusa era la corrispondente alla prima
        {
            sub_expr = malloc(it2 - it);                             // creo una sottostringa (sotto-espressione)
            sub_expr = memcpy(sub_expr, expression+it+1, it2-it-1);  // e gli ficco dentro il contenuto delle parentesi
            sub_expr[it2-it-1] = '\0'; 
            float_stack_push(&stack_num, evaluate(sub_expr));        // calcolo ricorsivamente (in realtà sono già dentro a evaluate) il risultato della sotto espressione
            it = it2;                                                // mi trovavo alla posizione contenente '(', ora salto alla posizione dove c'è ')'  
            break;                                                   // ho trovato la parentesi che mi chiude la '(' che avevo incontrato, stoppo il for
        }
    }
}

Se intendevi qualcos'altro prova a rispiegarti.

Comunque ogni tentativo d'aiuto, per stupido che sia, è ben accetto.
Non fatevi scrupoli a scrivere boiate, magari in un modo o nell'altro tornano utili!


Credo che i casi da contemplare siano talmente tanti... se poi pensi di tradurlo in ASM... è sconfortante
mhhae.gif

Se è proprio troppo difficile passo ad altro, ma non mollo senza averci manco provato.


Credo che sarei capace di farlo in C, ma non credo ti aiuterebbe.
Purtroppo non conosco il C

What?! :omfg:
Comunque mi interessa anche solo un ragionamento per risolvere un problema simile, poi ad implementarlo ci penso io. Lo farei prima in C (che rimane comunque molto low-level) per vedere se fila liscio, se è tutto ok poi passo all'assembly.
 
  • Mi piace
Reazioni: Simur Birkoff
[MENTION=156155]St3ve[/MENTION]

PHP:
/* questo è per il "risolvere" le singole parentesi... l'ho fatto col più e col meno ma si più facilmente riscrivere 
 * col * e il /
 * per la potenza è un'altra storia... vedi se è adeguato... 
 * non è neanche completo ma è la linea generale, almeno quella a cui pensavo io*/

#include<iostream>
#include<string>
#include<vector>

using namespace std;

int conv_str(string);

int main()
{
/*diamo per scontato che nella parentesi da analizzare le operazioni abbiano tutte la medesima priorità, e 
 * che le priorità siano invece definite tramite le parentesi stesse in modo più rigido.
 * anzi che   2+5*3-3/1   l'utente dovrà    2+(5*3)-(3/1)
 * un piccolo sforzo per l'utente, un grandissimo vantaggio per noi! Nonchè la maggiore facilità di gestione
 * degli errori.
 * sacrificio accettabile... per me almeno! :P */

  string esp, tmp;
  vector<char> op;
  vector<int> vals;
  int ris, i;
  
  cout<<"espressione = "; cin>>esp;
  tmp=esp;  //lavoro prima sui numeri con tmp senza rovinare esp e poi con esp sugli operatori
  
  for(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;  //questa riga mi è costata venti minuti di duro ragionamento! :|
    }
  }
  
  vals.push_back(conv_str(tmp));  // perchè l'ultimo valore resta escluso... poco male :)
 //ora abbiamo un vector con i numeri, inseriamo gli operatori nell'ordine giusto e il gioco è fatto! 
 
  for(i=0; i<esp.size(); i++)
  {
    if(esp[i]=='+')
      op.push_back('+');
    else if(esp[i]=='-')
      op.push_back('-');
  }  //ora abbiamo un vettore con le operazioni
  
  i=0;
  
  /*do
  {
    if(op[op.size()-i]=='+')
      ris=vals[vals.size()-1]+vals[vals.size()-2];
    else if(op[op.size()-i]=='-')
      ris=vals[vals.size()-1]-vals[vals.size()-2];
    
    vals.erase(vals.end()-1);
    vals.push_back(ris);
    vals.erase(vals.end()-2);
    i++;
    
  } while(vals.size()>1);
  
  * qui mi sono bloccato... non so se ti può essere utile ma se riesci a combinare i due vector per risolvere 
  * parentesi di pari priorità e riesci a estrarre di volta il volta le parentesi più esterne dall'espressione iniziale 
  * e a sostituire per ogni parentesi il suo risultato hai fatto... no? 
  * questo è quello che per ora ho scritto... domani mi ci metto di nuovo.*/
  
  cout<<ris<<endl;
  
  return 0;
}


int conv_str(string s)
{
  int num;
  
  if(s.size()==1)
    num=s[0]-48;
  
  else if(s.size()==2)
    num=((s[0]-48)*10)+(s[1]-48);
 
  else if(s.size()==3)
    num=((s[0]-48)*100)+((s[1]-48)*10)+(s[2]-48);
  
  else if(s.size()==4)
    num=((s[0]-48)*1000)+((s[1]-48)*100)+((s[2]-48)*10)+(s[3]-48);
  
  
  return num;
}
 
  • Mi piace
Reazioni: St3ve
Ultima modifica:
Se l'errore in è in fase di compilazione (come penso che sia) allora non credo che questa soluzione sia applicabile...

- - - Updated - - -


Come si convertono i char di operazione in operatori veri e propri?

No, non è in fase di compilazione.

Siccome io e l'assembly non andiamo d'accordo ti spiego come farlo in python poi vedi te.

Codice:
espressione=input("Scrivi l'espressione: ")
for elem in espressione:
    try:
        int(elem)
        print(elem + " è un numero!")
    except:
        print(elem + " non è un numero!")

Come puoi vedere dallo screen funziona:

Trma6UQ.png
 
  • Mi piace
Reazioni: Simur Birkoff
[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
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
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

St3ve

Utente Jade
12 Ottobre 2011
2,442
5
1,850
686
Conoscete un algoritmo semplice per risolvere espressioni di questo tipo: -5+2*(10-8)/2+5^3 ?

Non mi importa che sia efficiente, basta che sia il più semplice possibile visto che dovrei scriverlo in assembly.
 
Esatto, io ho una stringa che contiene un'espressione aritmetica e mi interessa elaborarla per poter ottenere il risultato.
Si tratta di individuare nella stringa gli ascii dal 48 al 57, convertirli in interi, individuare nella stringa gli operatori (*, +, -, /) e fare il calcolo... giusto? Non è per nulla facile. Soprattutto se il codice deve contemplare espressioni di lunghezza arbitraria... Io provo, in ogni caso mi interessa sapere come va a finire. :)

- - - Updated - - -

Rettifico, questo problema di parsing è fuori dalla mia portata e se c'è qualcuno in questo forum in grado di risolverlo con un codice intelligente, ottimizzato ed efficace... ecco, se c'è può diventare il maestro di tutti! :asd:
 
Penso che si possa risolvere in qualche modo con le Regex.
Il problema sta che in ASM non ho idea di come si possano implementare, in ogni caso si potrebbe fare un ragionamento del genere:
Non so se sia un ragionamento che fila ma potresti fare una MatchCollection delle parentesi EG: "\((.+)\)" e scorri la collection al contrario.
Per i calcoli puoi fare un ciclo per dare la precedenza (si è molto greed ma non mi è venuto in mente altro).
Senza le Regex il discorso è lo stesso, solo che diventa più complicato trovare le parentesi manualmente.
 
In python potresti utilizzare il ciclo for per ogni carattere e trasformarlo in un integer. Se ti dà errore, non è un numero (e poi vai a verificare cosa sia), mentre se non da errore il numero viene trasformato in integer e poi fai le operazioni. (ho fatto una cosa simile non molto tempo fa)
 
In python potresti utilizzare il ciclo for per ogni carattere e trasformarlo in un integer. Se ti dà errore, non è un numero (e poi vai a verificare cosa sia), mentre se non da errore il numero viene trasformato in integer e poi fai le operazioni. (ho fatto una cosa simile non molto tempo fa)
Se l'errore in è in fase di compilazione (come penso che sia) allora non credo che questa soluzione sia applicabile...

- - - Updated - - -

Penso che si possa risolvere in qualche modo con le Regex.
Il problema sta che in ASM non ho idea di come si possano implementare, in ogni caso si potrebbe fare un ragionamento del genere:
Non so se sia un ragionamento che fila ma potresti fare una MatchCollection delle parentesi EG: "\((.+)\)" e scorri la collection al contrario.
Per i calcoli puoi fare un ciclo per dare la precedenza (si è molto greed ma non mi è venuto in mente altro).
Senza le Regex il discorso è lo stesso, solo che diventa più complicato trovare le parentesi manualmente.
Come si convertono i char di operazione in operatori veri e propri?
 
Ultima modifica:
Penso che si possa risolvere in qualche modo con le Regex.
Il problema sta che in ASM non ho idea di come si possano implementare, in ogni caso si potrebbe fare un ragionamento del genere:
Non so se sia un ragionamento che fila ma potresti fare una MatchCollection delle parentesi EG: "\((.+)\)" e scorri la collection al contrario.
Per i calcoli puoi fare un ciclo per dare la precedenza (si è molto greed ma non mi è venuto in mente altro).
Senza le Regex il discorso è lo stesso, solo che diventa più complicato trovare le parentesi manualmente.

Le parentesi pensavo di gestirle in modo ricorsivo: quando trovo una parentesi aperta inizio a contarle (+1 per quelle aperte e -1 per quelle chiuse) e quando torno a 0 riapplico l'algoritmo di risoluzione sulla sottostringa che parte dopo la prima parentesi e termina prima dell'ultima parentesi trovata, che sarebbe quella che effettivamente chiude la prima parentesi aperta.
Ovviamente per semplificare sto dando per scontato che la stringa in input sia corretta.
La parte più difficile è tutto il resto. Il tuo ragionamento non mi è chiarissimo.


In python potresti utilizzare il ciclo for per ogni carattere e trasformarlo in un integer. Se ti dà errore, non è un numero (e poi vai a verificare cosa sia), mentre se non da errore il numero viene trasformato in integer e poi fai le operazioni. (ho fatto una cosa simile non molto tempo fa)

Trasformare da caratteri a numeri e capire se ho a che fare con un simbolo non è difficile nemmeno in assembly.
Sostanzialmente si tratta di scorrere carattere per carattere e verificare se il carattere attuale è compreso tra '0' e '9', se è così si avvia una routine di riconoscimento numerico altrimenti si da per scontato che è un simbolo.
Il problema è trovare un modo semplice per gestire la precedenza degli operatori e per effettuare i calcoli.

Come si convertono i char di operazione in operatori veri e propri?
La sostanza è questa:
Codice:
if(carattere == '+')
     ris = num_left + num_right;



Questo l'avevo visto, ma non l'ho capito più di tanto. Tu l'hai capito?



Comunque ieri ho cercato un algoritmo di parsing in giro per internet (se ritrovo il nome lo posto) e ho provato ad applicarlo in C. Con ~300 linee di codice ho qualcosa di abbastanza funzionante (mi da ancora problemi il - inteso come segno di negazione, come sottrazione funziona).
Se trovate qualche algoritmo semplice o se vi viene in mente qualcosa fatemi sapere, prima di scriverlo in assembly provo a scriverlo in C e vedo quanto è effettivamente semplice.

EDIT:
Ok, la prova che ho fatto io mi da ben più di un problema XD
Fatico a gestire le istruzioni a pari priorità.
 
[MENTION=156155]St3ve[/MENTION]
Credo che i casi da contemplare siano talmente tanti... se poi pensi di tradurlo in ASM... è sconfortante :\
In ogni caso credo che sia sufficiente l'analisi delle parentesi, nel senso che da sinistra a destra si scorre fino a trovare la parentesi, quando essa viene chiusa si esegue l'algoritmo solo su quella, si sostituisce nell'espressione il risultato e così via...

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

using namespace std;

int main()
{
  string exp;
  vector<char> cast;
  int i=0;
  
  cout<<"inserisci espressione: "; cin>>exp;
  
  while(i<exp.size())
  {
    if(exp[i]=='(' || exp[i]==')')
      cast.push_back(exp[i]);
    i++;
  }
  
  cout<<exp<<endl<<endl;
  for(i=0; i<cast.size(); i++)
    cout<<cast[i]<<" ";
  
  cout<<endl;
  
  return 0;
}

In base alla posizione in cui si trovano, cioè partendo dalla sinistra quando si verifica la condizione: "trovata parentesi aperta e trovata parentesi chiusa" si salvano le posizioni e si riempie con ciò che ci sta in mezzo, si risolve quello e si va a sostituire nella stringa... Più che altro è una domanda eh! :) Non voglio assolutamente insegnare niente a nessuno, solo, che te ne pare?
 
Ultima modifica:
Credo che sarei capace di farlo in C#, ma non credo ti aiuterebbe.
Purtroppo non conosco il C, nè l'assembly xD
 
[MENTION=156155]St3ve[/MENTION]
Ok steve l'algoritmo generale mi sebra chiaro, ciò che è difficile è tradurlo...


  • trovare tutte le parentesi e le loro posizioni nella stringa
  • verificare il contenuto della parentesi più interna
  • risolvere
  • 1) tradurre la stringa in intero dove ci sono numeri cercando ascii eccetera eccetera
  • 2) il rimanente sono sicuramente operazioni dato che non sono né parentesi né numeri
  • sostituire il risultato al posto della parentesi nella stringa... -> nuova stringa
  • loop

Eppure manca qualcosa :\
 
Scusami, ho editato, volevo scrivere C# la prima volta.
Ah ok, chiaro. Immaginavo fosse un errore di battitura.
Se il C# ha qualche magheggio che te lo fa risolvere in 5 secondi (tipo il python) lascia perdere, sarebbe inutile, se invece hai in mente un algoritmo per la risoluzine provaci pure.
Mi basterebbe capire bene cosa devo fare, poi a tradurlo in codice ci penso io. L'importante è che si riesca a trovare un algoritmo semplice, se è troppo contorto diventa troppo difficile tradurlo in assembly.

@St3ve
Ok steve l'algoritmo generale mi sebra chiaro, ciò che è difficile è tradurlo...


  • trovare tutte le parentesi e le loro posizioni nella stringa
  • verificare il contenuto della parentesi più interna
  • risolvere
  • 1) tradurre la stringa in intero dove ci sono numeri cercando ascii eccetera eccetera
  • 2) il rimanente sono sicuramente operazioni dato che non sono né parentesi né numeri
  • sostituire il risultato al posto della parentesi nella stringa... -> nuova stringa
  • loop

Eppure manca qualcosa
mhhae.gif

A me invece sfugge ancora l'algoritmo generale. Non ho ancora capito cosa fare, quel "risolvere" è troppo astratto.
Per ora sto usando una variante di questo:
Two stacks are required, one for numbers and the other for operators. The algorithm is:


  • For each item in the infix expression (no parens) from the right to the left
    • If the item is a number then push it on the number stack.
    • If the item is an operator (+,-,*, or /) and: the operator stack is empty or the operator on the top of the stack is higher in priority (* and / are higher in priority than + or -), then
      • Pop an operator from the operator stack.
      • Pop two numbers off the number stack.
      • Calculate using second number-operator-first number.
      • Push the result on the number stack.
      • Push the item on the operator stack.

    • Else push the item on the operator stack.

  • After the loop, while the operator stack is not empty
    • Pop an operator from the operator stack.
    • Pop two numbers off the number stack.
    • Calculate using second number-operator-first number.
    • Push the result on the number stack.

  • The answer is the last item in the number stack.

Che però non funziona come dovrebbe, sospetto che sia proprio un problema dell'algoritmo. Non ho problemi con roba tipo 100/5*2/3+(90/2*3-10)+10^2+5! ma se provo con 1-5*3+2*3+4*21-100/5*2+2 non funziona (il problema capita per colpa di quel +2 finale).
 
Sono abbastanza fiducioso di avere un algoritmo in testa... In serata te lo mostro! Ovviamente so qual é il livello che ci separa ma io la mia te la do comunque
 
In ogni caso per tradurlo in codice ASM puoi fermare il compilatore prima che generi l'eseguibile...
Per il g++ credo che sia
g++ -S nomefile.cpp -o nomefile
No?
 
Stato
Discussione chiusa ad ulteriori risposte.