Autore Topic: sottrazioni fra variabili float  (Letto 813 volte)

Offline Picavbg

  • Senatore Gambero
  • ******
  • Post: 1.620
    • Mostra profilo
sottrazioni fra variabili float
« il: 30 Ottobre 2011, 23:45:51 »
Durante una delle prove di prima rifinitura del mio programma di contabilità familiare, ho ottenuto un risultato a sorpresa:
Codice: gambas [Seleziona]
Dichiarazioni di Form03.class
PRIVATE f_SaldoFin AS Float
PRIVATE f_Sbilancio AS Float
PRIVATE f_TotResta AS Float

istruzioni inciriminate nella procedura CalcolaSbilancio()
.... bla ..... bla ..... bla .....
 f_Sbilancio = f_TotResta - f_SaldoFin
 IF f_Sbilancio >= 0 THEN   
    SbilancioMovvg.Foreground = Color.Foreground      'colore NERO
  ELSE
    SbilancioMovvg.Foreground = &H00FF0000&      'colore ROSSO
  ENDIF
.... bla ..... bla ..... bla .....


Ebbene, allorquando le variabili f_TotResta e f_SaldoFin contengano lo stesso valore (Es. 693,24), la loro differenza ottenuta nella variabile f_Sbilancio non é "0,00", bensì un valore strutturato similmente a "1,123456E05".

Per me il risultato ottenuto è assolutamente inspiegabile. Io ho risolto nel modo seguente:
Codice: gambas [Seleziona]
DIM $_TotResta AS String
DIM $_SaldoFin AS String
'---------------------------------------------------------------------------------------------------------------------
PRINT "Passaggio in CalcolaSbilancio"
'  IF f_TotResta = f_SaldoFin THEN
'      f_Sbilancio = 0
'  ELSE
  $_TotResta = CFloat(f_TotResta)
  $_SaldoFin = CFloat(f_SaldoFin)
  IF $_TotResta = $_SaldoFin THEN
      f_Sbilancio = 0
  ELSE
    f_Sbilancio = f_TotResta - f_SaldoFin
  ENDIF


Tuttavia, nonostante che la modalità applicata si sia dimostrata risolutiva, mi resta insoluta la domanda riguardante il perchè del malfunzionamento naturale dell'operazione originaria. ???

Mi potreste aiutare a capire?
Grazie anticipate.

A parte il caso specificato sopra, sto preparando una piccola presentazione del programma per eventuali test di amkici dotati di buona volontà e curiosità. :D
Ciao a tutti.
:ciao:

Offline md9327

  • Moderatore
  • Senatore Gambero
  • *****
  • Post: 2.840
    • Mostra profilo
Re: sottrazioni fra variabili float
« Risposta #1 il: 01 Novembre 2011, 23:04:09 »
Mica ho capito, sai?

Nella prima versione tu dici che, seppur le due variabili f_TotResta e f_SaldoFin siano uguali, in realtà non lo sono, riportando una strana differenza. La cosa non è possibile...
Trattare le tre variabili con tipo Float è corretto (se trattasi di valore monetario), mentre invece lavorando con le String potresti avere problemi se non opportunamente trattate.
Io credo faresti meglio ad utilizzare il debug, fermando l'esecuzione prima del calcolo, per controllare se le vars siano opportunamente impostate.

Infine, ricordo, che per la conversione da String a Float, utilizzando la funzione CFloat(), devi tener presente il carattere di separazione tra interi e decimali. CFloat() necessita di un valore contenente un punto, ed è indipendente dal formato di rappresentazione basato sulla lunga in uso. Il punto di separazione tra interi e decimali è definito a livello universale e matematico. La virgola viene utilizzata come carattere di separazione in alcuni paesi (es. Italia), ma è solo di presentazione!

Offline Picavbg

  • Senatore Gambero
  • ******
  • Post: 1.620
    • Mostra profilo
Re: sottrazioni fra variabili float
« Risposta #2 il: 02 Novembre 2011, 19:43:35 »
Grazie per la cortese risposta. Ero sicuro che mi avresti dato il tuo esperto parere. Andando con ordine, come detto nel messaggio d'apertura le due vraibili float, i f_TotResta e f_SaldoFin, contengano lo stesso valore, e ciò l'ho verificato tramite Debug; ho anche guardato il contenuto di f_Sbilancio  dopo l'operazione di sottrazione
Codice: [Seleziona]
f_Sbilancio = f_TotResta - f_SaldoFin 

ed ho constatato che era diverso da zero. Da ciò ho dedotto che i contenuti di f_TotResta e di f_SaldoFin, pur essendo apparentemente uguali, in realtà non lo sono, ma in fase di Debug non emerge.

Il trasferimento dei contenuti di  f_TotResta e di f_SaldoFin in altrettanti campi di tipo stringa serve solamente per testarne l'uguaglianza; infatti il contenuto di questi ultimi non viene assolutamente utilizzato dopo.il problema del punto per la divisione del numero intero da quello decimale nel formatco floating mi é noto, infatti, all'occorrenza, nel programma utilizzo due routine di conversione del punto decimale in virgola e viceversa.

Da tutto quello che mi hai suggerito, tuttavia, penso che non ci sono soluzioni alternative a quella da me adottata.
Grazie ancora.  :ciao:  :ciao:
:ciao:

Offline md9327

  • Moderatore
  • Senatore Gambero
  • *****
  • Post: 2.840
    • Mostra profilo
Re: sottrazioni fra variabili float
« Risposta #3 il: 02 Novembre 2011, 20:03:47 »
Più che soluzioni, questa mi sembra una vera anomalia.

Non sò come tu abbia testato il contenuto delle variabili, ed è quindi possibile che vi siano alcune differenze a livello di decimali, e se tu dici che sono uguali, questo potrebbe non essere proprio vero nei subdecimali.
Se la differenza si evidenzia sugli interi, il problema è che c'è un errore grossolano, altrimenti le differenze dovresti magari trovarle nelle cifre piccole, ad esempio:
Codice: [Seleziona]
DIM v1 AS Float = 1.0000000000000000000000000000000000000000000001
DIM v1 AS Float = 1.0000000000000000000000000000000000000000000002
In questo banale esempio, la differenza stà nella ennesima cifra decimale che, normalmente, viene ignorata per calcoli riferiti su valori monetari.
Un'altra cosa che mi può venire in mente è che è possibile che la cifra superi le dimensioni massime ammesse per un Float, e in questo caso il risultato può essere indefinito.
La conversione che hai fatto in String presumo sia stata effettuata su un valore di decimali definito e abbastanza piccolo (es. 6 decimali a norma bancaria). Se questo è vero, sicuramente il resto è stato giustamente troncato e perso, per cui la comparazione è risultata più idonea al tuo scopo.

Resto comunque dell'idea che vi sia un errore nel tuo codice, perchè diversamente la cosa la vedo alquanto brutta, perchè vorrebbe dire che esiste un problema serio nella gestione dei Float all'interno di Gambas.

Offline Picavbg

  • Senatore Gambero
  • ******
  • Post: 1.620
    • Mostra profilo
Re: sottrazioni fra variabili float
« Risposta #4 il: 04 Novembre 2011, 00:57:05 »
Mi rendo conto che non sempre le parole riescono a costruire l'immagine istantanea di quanto accada, perciò ho riattivato le istruzioni originarie, in modo da potere mostrare, in allegato,  il passo di programma interessato, con le istruzioni print relative al contenuto delle variabili, così come ho descritto nel mio messaggio d'aperura. Nella console, affiancata al detto passo di programma, potrai rilevare il contenuto delle variabili  f_TotResta f_SaldoFin f_Sbilancio e capire quello che volevo dire prima.
Per me è stato sempre incomprensibile il contenuto di f_Sbilancio, ma, personalmente, non credo che ci sia errore nel codice che ho scritto. Le variabili, inoltre sono dichiarate tutte della sezione "Dichiarazioni" della Form, come riportato nel 1° messaggio della presente discussione.
 :ciao: :ciao:
:ciao:

Offline md9327

  • Moderatore
  • Senatore Gambero
  • *****
  • Post: 2.840
    • Mostra profilo
Re: sottrazioni fra variabili float
« Risposta #5 il: 04 Novembre 2011, 11:29:43 »
Ho visto l'immagine, ma vedo anche che hai effettuato un semplice print delle variabile. Se non ricordo male Gambas dovrebbe riportare il valore Float con un massimo di 10 cifre, eventualmente condensato con un elevazione a potenza.
Nel print, invece, sono rpesenti solo due decimali, e presumibilmente sono veramente due. Per scrupolo dovresti provare a formattare il valore inserendo un numero maggiore di cifre, magari scopriamo che c'è effettivamente qualche differenza non visibile.
...è un tentativo...  :rolleyes:

Offline Picavbg

  • Senatore Gambero
  • ******
  • Post: 1.620
    • Mostra profilo
Re: sottrazioni fra variabili float
« Risposta #6 il: 05 Novembre 2011, 00:21:48 »
I valori monetari che hai visto nell'immagine che ti ho preparato ieri contengono sempre e solo due cifre decimali, quindi non posso fare da programma come mi suggerisci tu, però ho provato a forzare prima delle istruzioni print lo stesso valore e, modificando di volta in volta tale valore, ho svolto alcune prove. Ahimè, ho sempre ottenuto , dalla sottrazione successiva, sempre un risultato pari a zero.
Ecco le prove fatte:
f_TotResta= 650.12345678
f_SaldoFin= 650.12345678
f_Sbilancio= 0
---------------------------------
f_TotResta= 650.123
f_SaldoFin= 650.123
f_Sbilancio= 0
---------------------------------
f_TotResta= 650.12
f_SaldoFin= 650.12
f_Sbilancio= 0
---------------------------------
A questo punto non capisco dove possa risiedere il problema, anche perchè, nello svolgimento ordinario del programma, le istruzioni "PRINT" inserite, non hanno mai mostrato più di due cifre decimali ed i valori numerici si sono dimostrati, pertanto, sempre uguali; l'unica anomalia rilevata é comparsa solamente nel risultato della sottrazione. Francamente non riesco a capire come e dove cercare l'istruzione che genera valori float imprecisi.
 :ciao:
:ciao: