Valuta le espressioni matematiche senza stack

6

Come valuti espressioni matematiche arbitrarie usando variabili temporanee invece di uno stack? Quello di cui sto parlando è tradurre un'espressione in una serie di semplici operazioni, ognuna delle quali modifica una variabile in base al secondo argomento.

Un esempio di elenco di operazioni potrebbe essere:

=
+=
-=
*=
/=

Si noti come ogni operazione cambia il primo argomento. (nessuno di loro "restituisce" nulla)

Ecco una semplice espressione: (ho postfix con la profondità scritta anche sotto)

x=2+a*(b+c)
x 2 a b c + * + =
0 1 2 3 4 3 2 1 0


x=c
x+=b
x*=a
x+=2

Nota come non hai bisogno di variabili temporanee.

Ecco un'espressione che richiede una variabile temporanea:

x=a*(b+c)+d*(e+f)
x a b c + * d e f + * + =
0 1 2 3 2 1 2 3 4 3 2 1 0

x=b
x+=c
x*=a
tmp=e
tmp+=f
tmp*=d
x+=tmp 

Non riesco a capire una soluzione algoritmica per ottenere questi gruppi di operazioni. La necessità di variabili temporanee sembra avere qualcosa a che fare con gli operatori con precedenza inferiore che hanno come risultato gli operatori con precedenza più alta come argomenti, ma non posso dirlo.

Mi sento stupido ... Il modo mi sembra giusto ma non riesco a vederlo. Ovviamente si potrebbe fare il modo "facile"; AKA, crea una variabile temporanea per archiviare il risultato di ogni operazione in modo che nessuna operazione sia distruttiva per qualsiasi cosa eccetto ciò che hai messo prima del = , ma questo è male e non mi piace. Come puoi ottenere "l'algoritmo" per un'espressione nella forma più semplice?

EDIT: A causa della mia stessa ambiguità, devo chiarire che uno stack è permesso in translation , ma non nel linguaggio psuedo di fine che sto producendo.

    
posta TND 02.01.2013 - 03:28
fonte

4 risposte

5

Ecco un suggerimento.

Crea un albero di analisi. Riordinalo in modo che la parte più profonda dell'albero sia a sinistra, e fallo ricorsivamente.

Ogni "catena crescente" nell'albero di analisi non ha bisogno di provvisori. Ogni volta che incontri un nodo con bambini su entrambi i lati, avrai bisogno di un temporaneo. Se elabori l'intero albero, puoi scoprire il numero massimo di provvisori di cui hai bisogno in qualsiasi momento.

Non ho provato a dimostrare che questa soluzione golosa è veramente ottimale, ma scopre la migliore risposta in casi semplici e in tutti i casi otterrai una risposta con un numero limitato di provvisori.

    
risposta data 02.01.2013 - 07:23
fonte
4

Ecco un modo:

Inizia con la tua espressione:

x=2+a*(b+c)

Scrivi le operazioni di stack che verrebbero utilizzate:

PUSH b
PUSH c
ADD
PUSH a
MULTIPLY
PUSH 2
ADD
STORE x

Sostituisci PUSH seguito da un'operazione matematica da un'operazione matematica sul posto

PUSH b
IADD c
IMULTIPLY a
IADD 2
STORE x

Usa semplicemente variabili e temp per ogni posizione nello stack. La prima posizione sarà x e il resto sarà temp

x = b
x += c
x *= a
x += 2
    
risposta data 02.01.2013 - 17:57
fonte
2

Se sto capendo correttamente il tuo problema, guarda gli algoritmi usati dal compilatore per compilare le espressioni per le macchine con registri mentre cerchi di usare il minor numero possibile di registri. Ad esempio questo è un approccio classico e più moderno che utilizza la colorazione del grafico.

    
risposta data 02.01.2013 - 11:51
fonte
0

Quindi questo sarebbe un problema:

x=(a*b)+(c*d)

Supponendo che né ab sia zero, quindi calcola il (a*b) term:

x = (1+(c*d)/(a*b))*(a*b)

x=c
x*=d
x/=a
x/=b
x+=1
x*=a
x*=b

Come ho detto, se a o b è zero, devi prima ridurre il calcolo a:

x=c*d
    
risposta data 02.01.2013 - 15:31
fonte

Leggi altre domande sui tag