Newsgroup: it.comp.lang.vo-clipper
Titolo: Summa con Decimali

se faccio la somma di due numeri con decimali e la confronto con una
variabile che ha lo stesso valore
mi dice che è maggiore  analizzate questo esempio:
***** Somma il num1 + num2 e confronto il rusultato con num4
***** Vedete cosa succede con questi numeri gi. preimpostati
clear
store 0 to num1,num2,num4
num1=123.45
num2=24.69
num4=148.14
@ 10,10 say  ' Primo Num. ' get num1  picture '99999.99'
@ 11,10 say  ' Secon Num. ' get num2  picture '99999.99'
@ 14,10 say  ' Risul Num. ' get num4  picture '99999.99'
read
var1=num1+num2
***  provate a compilare prima senza queste due righe e poi includendole
* var1=str(var1,15,2)
* var1=val(var1)
@ 16,10 say var1
@ 17,10 say num4
if var1>num4
  @ 18,1 say 'Maggiore'
endif
if var1<num4
  @ 18,1 say 'Minore'
endif
if var1=num4
  @ 18,1 say 'Uguale'
endif

 wrote in message
5ocg7.582$IM1....@news.infostrada.it...


 mi dice che è maggiore  analizzate questo esempio:
E' normale. Fa parte dell'errore insito nella rappresentazione binaria
dei numeri frazionari. Trovi comportamenti analoghi in tutti i linguaggi
di programmazione. Una soluzione semplice potrebbe essere quella di
arrotondare i numeri da confrontare alla cifra decimale desiderata:
num4 = ROUND( num4, 2 )
var1 = ROUND( var1, 2 )
EMG

 perchè non e uguale??
Perché il risultato della somma parte da due numeri già approssimati e
quindi è ancora più soggetto ad errore (sempre molto piccolo). Mentre il
numero specificato direttamente come costante probabilmente viene
memorizzato in modo diverso.
EMG
PS. Non ricordo bene come sono memorizzati i numeri in Clipper. Se sono
in rappresentazione decimale (non binaria) il discorso è simile: il
risultato di un'operazione viene comunque approssimato rispetto alla
semplice costante.

...(megacut)
Come gia' detto da EMG l'errore proviene dagli arrotondamenti dovuti
al formato di memorizzazione dei numeri decimali.
Clipper memorizza questi ultimi nel formato standard IEEE
corrispondente al tipo <double> nel linguaggio C.
Il formato prevede 1 bit di segno, 11 bit di esponente (mod 1023) e
53 bit per la mantissa.
La soluzione che ho adottato io e' scrivere 3 mini-funzioni per le
operazioni di
confronto tra numeri decimali, in quanto anche la ROUND() mi ha dato qualche
problema:
Es. (confronto di uguaglianza con 2 decimali):
FUNCTION F_EQ(v1,v2)
RETURN VAL(STR(v1,15,2)) == VAL(STR(v2,15,2))
Poi ovviamente il confronto diventa :
IF F_EQ(var1,var2)
...
ENDIF
Ciao
Paolo R.

PS. Non ricordo bene come sono memorizzati i numeri in Clipper.
Sono _SEMPRE_ dei double in formato microsoft (altmath.lib), cioe'
floating point a 8 byte quindi sempre approssimati ma con 16 cifre
significative.
Stando cosi' le cose non ci dovrebbe essere nessuna perdita per
arrotondamento, probabilmente un bug nella str() o nella val(),
bisognerebbe controllare l'output di queste funzioni (io sono troppo
pigro!).
Sapevo di un bug nell'operatore % (modulo)...
ciao, acc.   
a...@libero.it

 problema:
E' vero, la funzione ROUND() ha qualche bug ma è un problema di
quest'ultima, non della tecnica di confronto tramite essa. Comunque mi
pare di ricordare di aver visto da qualche parte una sostituta della
ROUND() (in sorgente) che risolveva ogni problema (forse ce l'ho su
qualche dischetto).
EMG

 Sapevo di un bug nell'operatore % (modulo)...
Oh, non stai seguendo bene il discorso (il caldo?). Il problema
*spariva* utilizzando la STR() e la VAL(). Al limite il bug potrebbe
essere negli operatori logici di confronto.
EMG

Permettetemi di dirvi che io vivo con il problema da parecchio tempo, ogni
volta che devo confrontare il risultato di due numeri con virgola e
decimali tengo il cuore in mano,
specialmente quando si tratta di confrontare una variabile con un campo,
per sicurezza utilizzo
val(ntrim()) per tutte due i valori per essere certo del risultato,
sicuramente visual object ha un modo strano di immagazzinare i valori
numerici in memoria.
Per esempio avendo set decimal 2, trovi dei numeri dopo la seconda cifra
decimale non appena setti decimal a qualcosa in più di due.
Se qualcuno scopre qualche soluzione mi farebbe un grande piacere, perché
seriamente, in azienda comminiamo a mettere VO in seria discussione e
cerchiamo un alternativa. In quanto val(ntrim()) per ogni confronto
degrada seriamente l’efficienza del SW quando si tratta di Real Time
programmino.


 programmino.
Non dipende da VO, da Clipper né da qualunque altro linguaggio. E' un
problema, lo ripeto, insito nel fatto che i numeri vengono memorizzati
in binario ma immessi e visualizzati in decimale. Pensa che pare che
perfino un missile durante la guerra del golfo sbagliò bersaglio a causa
di queste approssimazioni.
Che io sappia, il sistema migliore è quello di tener conto di un certo
epsilon abbastanza piccolo mentre si fanno i confronti. Praticamente, se
due numeri differiscono di una quantità minore di questo epsilon sono da
considerarsi uguali.
EMG

essere negli operatori logici di confronto.
Confermo al 100% ho fatto le prove col C 7.0 di m$ compilando con la
altmath.lib il programma che segue:
#include <stdio.h>
void main() {
	double num1 = 123.45;
	double num2 = 24.69;
	double num4 = 148.14;
	double var1 = num1 + num2;
	printf("%.20f  %.20f\n", var1, num4);
	printf("%s\n", (var1 > num4) ? "Maggiore" : (var1 < num4) ?
"Minore" : "Uguale");
	printf("%.20f\n", var1 - num4);
}
Ecco il risultato:
148.14000000000000000000  148.14000000000000000000
Maggiore
0.00000000000002842171
Interessante pero' e' che il risultato e' identico usando la libreria
floating point standard.
Stesso problema utilizzando dei long double (80 bit). La differenza in
questo caso diventa:
0.0000000000000177635683940025
ciao, acc.   
a...@libero.it

 0.00000000000002842171
Come volevasi dimostrare. Stesso risultato con Borland C++ 5.5 e DJGPP.
EMG

 wrote in message
3B84A2B9...@flashnet.it...


 comandi?
Prova un po' con la funzione L2BIN()...
EMG

 wrote in message
3B83EAC8...@tin.it...


 RETURN AbsFloat(FLOAT(uV1)-FLOAT(uV2)) < POW(10, -1*nDec)
Ma che č?
EMG

 wrote in message
3B8D5D4D...@flashnet.it...


 tra due numeri ad una certa cifra decimale.
Peccato che l'amico, se non vado errato, parlava di Clipper...
EMG

 > > Ma che è?


 Abdul e non a Pablo2.
Ah, allora chiedo venia. Comunque propongo di puntualizzare bene di
quale strumento si sta parlando quando si scrive altrimenti creiamo solo
confusione.
EMG

 wrote in message
3B911B42...@flashnet.it...


 non siano poi cosi' diversi.
Mah, secondo me il codice che avevi scritto non sarebbe stato di nessun
aiuto ad uno che cercava di risolvere il problema in Clipper.
EMG