Domanda

Salve, mi chiedevo se esiste un modo noto per eliminare le parentesi non necessarie nelle formule matematiche.Il motivo per cui sto ponendo questa domanda è che devo ridurre al minimo la lunghezza della formula

if((-if(([V].[6432])=0;0;(([V].[6432])-([V].[6445]))*(((([V].[6443]))/1000*([V].[6448])
+(([V].[6443]))*([V].[6449])+([V].[6450]))*(1-([V].[6446])))))=0;([V].[6428])*
((((([V].[6443]))/1000*([V].[6445])*([V].[6448])+(([V].[6443]))*([V].[6445])*
([V].[6449])+([V].[6445])*([V].[6450])))*(1-([V].[6446])));

fa fondamentalmente parte dell'istruzione select SQL.Non può superare 255 caratteri e non posso modificare il codice che produce questa formula (fondamentalmente una scatola nera;)) come vedi molte parentesi sono inutili.Senza contare il fatto che:

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

Quindi voglio mantenere l'ordine delle operazioni Parentesi, Moltiplica/Dividi, Aggiungi/Sottrai.

Sto lavorando in VB, ma la soluzione in qualsiasi lingua andrà bene.

Modificare

Ho trovato un problema opposto (aggiungere parentesi a un'espressione) Domanda.

Pensavo davvero che ciò potesse essere realizzato senza un'analisi pesante.Ma sembra che un parser che esamini l'espressione e la salvi in ​​un albero delle espressioni sia inevitabile.

È stato utile?

Soluzione

Potresti eliminare i casi più semplici:

([V].[6432]) and (([V].[6443]))

Diventa

v.[6432]

Non dovrebbe essere necessario il [] attorno al nome della tabella o al suo alias.

Potresti accorciarlo ulteriormente se puoi creare un alias per le colonne:

select v.[6432] as a, v.[6443] as b, ....

O anche inserire tutte le tabelle interrogate in un'unica sottoquery, quindi non avresti bisogno del prefisso della tabella:

if((-if(a=0;0;(a-b)*((c/1000*d
+c*e+f)*(1-g))))=0;h*
(((c/1000*b*d+c*b*
e+b*f))*(1-g));

select [V].[6432] as a, [V].[6445] as b, [V].[6443] as c, [V].[6448] as d, 
    [V].[6449] as e, [V].[6450] as f,[V].[6446] as g, [V].[6428] as h ...

Ovviamente questo è tutto un po' di pseudocodice, ma dovrebbe aiutarti a semplificare l'intera dichiarazione

Altri suggerimenti

Se siete interessati a rimuovere la parentesi non necessarie nella vostra espressione, la soluzione generica consiste nel parsing il testo e costruire l'albero di espressione associato.

Quindi, da questo albero, è possibile trovare il testo corrispondente, senza non necessaria parentesi, mediante l'applicazione di alcune regole:

  • se il nodo è un "+", senza parentesi sono richieste
  • se il nodo è un "*", quindi le parentesi sono necessarie per la sinistra (a destra) bambino solo se la sinistra (a destra) bambino è un "+"
  • la stessa domanda per "/"

Ma se il vostro problema è solo quello di affrontare questi 255 caratteri, probabilmente si può semplicemente usare variabili intermedie per memorizzare i risultati intermedi

T1 = (([V].[6432])-([V].[6445]))*(((([V].[6443]))/1000*([V].[6448])+(([V].[6443]))*([V].[6449])+([V].[6450]))*(1-([V].[6446])))))
T2 = etc...

So che questa discussione è molto vecchio, ma come è consultabile da parte di Google.

Sto scrivendo un programma di TI-83 Plus calcolatrice che affronta problemi simili. Nel mio caso, io sto cercando di risolvere in realtà l'equazione per una variabile specifica in numero, ma può comunque riguardare il problema, anche se sto utilizzando una matrice, quindi potrebbe essere più facile per me scegliere valori specifici. ..
Non è ancora finito, ma non sbarazzarsi della stragrande maggioranza delle parentesi con (credo), una soluzione un po 'elegante.

Quello che faccio è eseguire la scansione attraverso l'equazione / funzione / qualunque cosa, tenendo traccia di ogni Parenthese apertura "(" finché non trovo una parenthese di chiusura ")", a quel punto posso essere sicuro che io non incorrere in alcuna più profondamente nidificate Parenthese.

y = ((3x + (2))) sarebbe visualizza (2), e poi il (3x + (2)), e quindi la ((3x + 2))).

Ciò che fa è allora controlla i valori immediatamente prima e dopo ogni Parenthese. Nel caso di cui sopra, che sarebbe tornato e +). Ognuno di questi viene assegnato un valore numerico. Tra i due, viene utilizzato il più alto. Se non vengono trovati gli operatori (*, /, +, ^, o -). I DEFAULT ad un valore di 0

Poi ho la scansione attraverso l'interno delle parentesi. Io uso un sistema di numerazione simile, anche se in questo caso uso il valore più basso trovato, non il più alto. Ho Default per un valore di 5, se non viene trovato nulla, come sarebbe nel caso di cui sopra.

L'idea è che si può assegnare un numero alla importanza delle parentesi sottraendo i due valori. Se si dispone di qualcosa come un ^ al di fuori delle parentesi (2 + 3) ^ 5 queste parentesi sono potenzialmente molto importante, e sarebbe dato un valore elevato, (nel mio programma che uso per 5 ^).

È possibile tuttavia che gli operatori all'interno renderebbero le parentesi molto importante, (2) ^ 5 dove nulla è stato trovato. In tal caso l'interno verrebbe assegnato il valore 5. Sottraendo i due valori, è possibile determinare se una serie di parentesi è neccessary semplicemente controllando se il numero risultante è maggiore di 0. Nel caso di (2 +3) ^ 5, un ^ darebbe un valore di 5, e un + darebbe un valore di 1. Il numero risultante sarebbe 4, che indicherebbe che le parentesi sono infatti necessari. Nel caso di (2) ^ 5 si avrebbe un valore interno di 5 e un valore esterno 5, risultante un valore finale di 0, dimostrando che le parentesi sono importanti, e possono essere rimosse.

Lo svantaggio di questo è che, (almeno sul TI-83) di scansione mediante l'equazione tante volte è incredibilmente lento. Ma se la velocità non è un problema ... Non so se che vi aiuterà a tutti, potrei essere completamente fuori tema. Spero che hai tutto e funzionante.

Sono abbastanza sicuro che al fine di determinare quali parentesi non sono necessarie, sono per valutare le espressioni al loro interno. Poiché è possibile parentesi nidificare, questo è il tipo di problema ricorsivo che un'espressione regolare può affrontare solo in modo superficiale, e più probabilità di risultati non corretti. Se sei già valutando l'espressione, forse vuoi per semplificare la formula, se possibile. Questo diventa anche un po 'difficile, e in alcuni approcci utilizza tecniche che che sono visti anche in apprendimento automatico, come si potrebbe vedere nel seguente articolo: http://portal.acm.org/citation.cfm?id=1005298

Se i nomi delle variabili non cambiano significativamente da 1 query per il prossimo, si potrebbe provare una serie di sostituzione () comandi. cioè.

X=replace([QryString],"(([V].[6443]))","[V].[6443]")

Inoltre, perché non può superare 255 caratteri? Se si archiviano questo come un campo di stringa in una tabella di Access, allora si potrebbe provare a mettere la metà l'espressione nel campo 1 e la seconda metà di un altro.

Si potrebbe anche provare l'analisi l'espressione usando ANTLR, yacc o simili e creare un albero sintattico. Questi alberi di solito ottimizzano parentesi distanza. Poi si sarebbe solo dovuto creare un'espressione indietro da un albero (senza parentesi, ovviamente).

Si potrebbe prendere più di un paio d'ore per ottenere questo lavoro però. Ma l'espressione analisi di solito è il primo esempio in analisi generiche, per cui si potrebbe essere in grado di prendere un campione e modificarlo per le vostre esigenze.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top