Newsgroup: it.comp.lang.visual-basic
Titolo: [?]Testare parser di espressioni algebriche

Vediamo un po': ho scritto una funzione ("valuta") che legge un'espressione
algebrica sotto forma di stringa, ne valuta il valore seguendo le parentesi e la
priorità degli operatori e restituisce il risultato sotto forma di stringa con
le cifre decimali desiderate (in caso di divisione o esponenziale negativo).
Gestisce gli operatori *,+,-,/,! e ^, quest'ultimo solo per esponenti interi.
Utilizza per i calcoli la mia lentissima ed esosissima classe a precisione
arbitraria.
Per cui è possibile valutare espressioni come 
"3!!!*(2^-256)" 
Siccome la cosa l'ho fatta di fretta, mi trovo nell'imbarazzo di non essere
sicuro che la funzione faccia il suo dovere in tutte le situazioni (mentre la
perfezionavo ho notato che spesso sbagliava il segno del risultato finale, ora
questo aspetto dovrebbe essere a posto).
Qualcuno ha idea di come posso testare in modo abbastanza sicuro ma non troppo
impegnativo la funzione?
Pensavo di generare casualmente varie espressioni, usare le librerie di M$ per
valutarle, usare la mia funzione per valutarle e confrontare il risultato...
Ho paura però di perdere svariate casistiche.
Con(s)igli?
termoPilucco.

 Con(s)igli?
Consigli no, ma complimenti si.
Nonostante la tua classe non sia velocissima, devo ammettere che hai fatto
un ottimo lavoro (ho studiato un bel po di roba di quella classe per
capirla)
bye
-- 
Esistono 10 tipi di persone: chi conosce il binario e chi no.
Gestione Ottica - Gestionale per Ottici e Programmi Gratuiti su:
http://www.nicolaottomano.it

capirla)
Grazie :)
Comunque quando sono partito volevo fare una cosa accademica con algoritmi delle
operazioni esattamente come vengono insegnati alle scuole elementari.
Poi, pian piano, Newton ed altri mi sono venuti in aiuto :)
Adesso mi chiedo per quale ragione alle elementari non insegnino l'algoritmo di
Newton anzichè quello tradizionale :P
Nell'ultima versione ho velocizzato la somma (di conseguenza divisione e
moltiplicazione) del 40% operando con 8 cifre alla volta (gestibili tramite
long) anzichè una come nell'algoritmo che ci insegnano alle elementari.
Non ho ancora fatto l'upload... lo farò quando sarò abbastanza sicuro che la
funzione "valuta" faccia quello che dice.
termoPilucco

 Con quindici ore di CPU al 100%  ;-)
UBASIC, un semplicissimo basic con matematica a precisione arbitraria (con i
numeri di linea, "10 GOSUB 200", che nostalgia!) ci mette una frazione di
secondo!
10 PRINT !(!(!(3)))*2^(-256)
RUN
2246456524533891036663561277199935516328234520530628404566643342402974908218
826
1195644165619081630604960670241380235593362456370337187784365832440362891011
8645
0007724778112401715617673448575140519155089777381167793637319736589131791162
7793
4557799799271970484983469665830881014773480263363643814934131386142646377608
8827
6615116739265808599250352923492859566888569500346643343997081376307899252503
8307
0795959596753272592836097922190186261365538233821117777126281848481501269318
3406
3197714067880721798030365153975836068154223986008694204264881282000391357743
4830
5568306888914292989916312086058978700951372282717465241209768633564699901415
4643
0409344063714444904847596906611199425013213026652013269656682872278733753152
1201
5959441067811970016287165826350758532416779999004015279914523068103661942168
8625
7788336706620382662339944145904732195792022832194789649635471941365517549585
3132
8986052769512661784666136339019427138734984090809761301798001098732303892540
3863
5826661178037522337518501346967009007945247472631197887751191856423611564117
9383
2876611097438349646541393283807249363336267868386990012243454776026904283018
2897
0911617076124488075514613355540051216155471342449338628962610108484522218254
5289
2457265453149136871295692054461186726127507969522892802440156281386417173383
2125
0594141299188264089716629411514974625884269576656219549903764983956987791344
7362
1740665447002427606230449376556064138635212978884530093395209715169920993853
9095
6942056253669911547059184734553945622984498066594201600000000000000000000000
0000
0000000000000000000000000000000000000000000000000000000000000000000000000000
0000
00000000000000000000000000000000000000000000000000000000000000000000000
OK
-- 
Ciao, Silv:o)

 arbitraria.
Ummm... e perchè non hai usato il Microsoft Script Control o la mia 
classe (vedi firma) che nei miei test è risultata circa il 20/25% più 
veloce dell'MsScriptControl seppur scritta in VB6?
Curiosità: che algoritmo hai usato per il parsing?
Per il test ti posso consigliare qualcosa da quelli che ho fatto io:
- controllo delle precedenze, con e senza parentesi e con più parentesi 
annidate.
- controllo degli operatori unari e della loro precedenza con e senza 
parentesi (-n, not n, n!)
- controllo della possibile combinazione tra operatori
(es. n + - -n, n * -n, n * -n ^ -m)
- controllo della possibilità di iniziare un'espressione con gli 
operatori unari ma non con i binari (-n * m è valido, * m - n non è valido)
Ciao
-- 
Math Parser : 
http://www.neodatatype.net
Sito Comune : 
http://www.it-lang-vb.net

frazione di secondo!
Che sia semplicissimo da usare non significa che sia stato semplice da
creare per i programmatori :)
termoPilucco
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 operatori unari ma non con i binari (-n * m è valido, * m - n non è valido)
ehm... per ora assumo che l'espressione sia sintatticamente corretta,
ovvero cerco di eseguirla bovinamente.


 operatore binario.
Perchè questo devi tradurlo in modo differente: se il "token" precedente 
  è un "valore" allora è il "-" binario, se il token precedente è 
un'operatore (si assume che all'inizio del parsing si sia in questa 
condizione) allora è unario, lo rimpiazzo con "~" e così so che quando 
valuto l'espressione devo trattarlo come "-" unario.


 valuto l'espressione devo trattarlo come "-" unario.
Io alla fine ho risolto considerando "-b" come caso base.
In questo modo valutando a*-b prendo -b direttamente come numero anzichè
come operatore e numero.
Magari però così qualcos'altro smette di funzionare :-/


 Magari perň cosě qualcos'altro smette di funzionare :-/
Non dovrebbe se hai considerato casi e precedenze tipo
-(b), -(a+b) -b^2 (che equivale a -(b^2) e non a (-b)^2)


 -(b), -(a+b) -b^2 (che equivale a -(b^2) e non a (-b)^2)
Ho detto una cavolata, -b ^ 2 equivale a (-b) ^ 2
vedi ad es. 
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/jscript7/html/jsoperatorprecedence.asp


 Ho detto una cavolata, -b ^ 2 equivale a (-b) ^ 2
uhm... tu, a "mano", come calcoleresti 8 - 2 ^ 2 ?
-- 
Salutoni
Sergio
per rispondere... togli il group dall'indirizzo

 Ho detto una cavolata, -b ^ 2 equivale a (-b) ^ 2
VB non è daccordo:
? -9 ^ 2 
-81
quindi valuta -(9^2)


 semplice da creare per i programmatori :)
Tutt'altro! Secondo me hanno fatto un lavoro pazzesco.
L'interfaccia è ridicola (l'editor praticamente non esiste, gira tutto su
console dos), ma il motore è eccezionale. Ha delle routine molto efficienti
per i test di primalità e moooolto altro ancora.
Seguendo il thread mi è venuta la curiosità di vedere se le previsioni
geologiche di Nicola sui tempi di calcolo erano in qualche modo fondate.
Così, solo per giocare. Allora ho riesumato il dinosauro ubasic e come al
solito mi ha impressionato ;) Altro che due minuti belzebù!
Falla un po' in .NET 'sta cosa, và :)
-- 
Ciao, Silv:o)

 E come fai a capire quando prendere -b?
in effetti in alcuni casi non riesco a vedere -b come pezzo unico :)
vediamo un po' i casi che hai citato:
-(b), -(a+b),  -b^2
nelle prime due espressioni le parentesi spariscono al primo giro ed
ottengo 
-b,   -c      dove c=a+b
a questo punto -b e -c sono casi base.
Nella terza espressione in effetti l'operatore ^ cerca i membri a destra e
a sinistra e trova b e 2
quindi calcola b al quadrato=d e poi si trova il caso base -d
boh, per ora i test li ho passati ma non fido ancora...


 quindi valuta -(9^2)
In effetti la cosa mi aveva dato dei problemi :)
Guarda qui:
http://groups.google.it/groups?hl=it&lr=&ie=UTF-8&q=zanna+elevamento+a+potenza&btnG=Cerca&meta=group%3Dit.comp.lang.visual-basic
e avevo chiesto addirittura qui
http://groups.google.it/groups?hl=it&lr=&ie=UTF-8&q=zanna+elevamento+a+potenza+group%3Ait.scienza.matematica+&btnG=Cerca


 Falla un po' in .NET 'sta cosa, và :)
credo che in .NET possa essere più preformante di VB6


 credo che in .NET possa essere più preformante di VB6
Può essere, non dico di no. Ma quel software di cui parlo, ubasic, credo sia
scritto in un linguaggio molto vicino al codice macchina e mi pare
ultraottimizzato.
A me .NET piace enormemente, ma più che altro perché ha spostato l'enfasi
sull'architettura delle applicazioni fornendo strumenti di una produttività
sconvolgente.
-- 
Ciao, Silv:o)

 e come premo invio appare il risultato di diverse centinaia di cifre.
non male come risultato :-)
Però tieni conto che la classe di termoPilucco può supportare fino a 2
miliardi di cifre... tante quante ne può contenere una textbox.
E' chiaro che nell'utilità pratica non serviranno mai 2 miliardi di cifre...
