Autore Topic: Query SQLite che restituisce risultato bizzarro!  (Letto 671 volte)

Offline wlf

  • Utente normale
  • ***
  • Post: 357
  • Respect: +8
    • Mostra profilo
  • Dispositivo Android:
    Xperia
Query SQLite che restituisce risultato bizzarro!
« il: 25 Luglio 2014, 09:23:44 CEST »
0
Salve,
nel DbAdapter ho inserito un metodo che mi restituisce il totale di tutta una serie di movimenti DARE ed AVERE che posso inserire:

Codice (Java): [Seleziona]
        public float getTotal() {
                float Totale = 0;
                if (database.isOpen()) {
                        Cursor myCursor = database.query(DbHelper.DATABASE_TABLE,
                                        new String[] { "SUM(IMPDARE) - SUM(IMPAVERE)" }, null, null, null,
                                        null, null);
                        myCursor.moveToFirst();
                        if (myCursor.moveToFirst()) {
                                Totale = myCursor.getFloat(0);
                        }
                        myCursor.close();                      
                }
                return Totale;
        }

La cosa strana è che mi è capitato che mi restituisca un valore come assurdo esponenziale come -7.10E-15 quando però effettivamente il totale esatto era 0. Con alcuni smartphone mi da tranquillamente 0, mentre con altri la somma da dei valori esponenziali di questo tipo.  ???
I campi DARE ed AVERE nel DbHelper sono stati dichiarati "numeric". Sapreste dirmi a cosa è dovuto questo "bizzarro" comportamento? :-o

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:Query SQLite che restituisce risultato bizzarro!
« Risposta #1 il: 25 Luglio 2014, 10:10:25 CEST »
0
Sapreste dirmi a cosa è dovuto questo "bizzarro" comportamento? :-o

Potrebbe essere dovuto al fatto che un numero "apparentemente" normale potrebbe non essere esprimibile in modo esatto nel formato "virgola mobile" usato dalla CPU.

Detto in altro modo. Prendi l'intervallo di numeri con la virgola tra 0,0 e 1,0 : in quell'intervallo ci sono INFINITI numeri. Prendiamo ora il formato di numeri in virgola mobile a 32-bit: degli infiniti numeri tra 0,0 e 1,0 solo una piccolissima parte possono essere rappresentati esattamente, gli altri sono approssimati a quello rappresentabile più vicino.

E non conta niente quante sono le cifre decimali nel formato "decimale", quello che conta sono le cifre dopo la virgola nel formato "binario".

Esempio:
Numero decimale : 0.1
La rappresentazione binaria interna è : 0.00011001100110011001100110011001100110011001100110011010
Che è anche la rappresentazione del numero decimale : 0.1000000000000000055511151231257827021181583404541015625

Quello che accade è che in operazioni apparentemente banali e ovvie in decimale, passando dalla rappresentazione binaria si possono generare errori.
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline wlf

  • Utente normale
  • ***
  • Post: 357
  • Respect: +8
    • Mostra profilo
  • Dispositivo Android:
    Xperia
Re:Query SQLite che restituisce risultato bizzarro!
« Risposta #2 il: 25 Luglio 2014, 11:37:38 CEST »
0
Potrebbe essere dovuto al fatto che un numero "apparentemente" normale potrebbe non essere esprimibile in modo esatto nel formato "virgola mobile" usato dalla CPU.

E' chiaro che numeri apparentemente normali, come 0.10, 0.15, etc scritti sui record del DB SQLite quando vengono sommati finendo in un Float, nel mio caso, sono diventati 0.099999999999999999999999999999.... un numero molto prossimo al 0.10 originale.
Per ovviare a questo problemino ho tentato modificando il mio metodo getTotal con un Double contando sul diverso livello di approssimazione supponendo non sarebbe emersa con un Double. Peccato che con un double ho lo stesso problema ma amplificato considerando che si verifica anche con un livello di precisione minore! :(

Rimango perplesso sul fatto che ci siano degli smartphone che non hanno alcun problema, altri invece sono "problematici". :(

Comunque sia c'è una soluzione oppure devo cercare di arrotondare?

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:Query SQLite che restituisce risultato bizzarro!
« Risposta #3 il: 25 Luglio 2014, 11:44:31 CEST »
0
Comunque sia c'è una soluzione oppure devo cercare di arrotondare?

Dovendo memorizzare dei numeri in virgola mobile in un database, se non ci sono problemi "particolari" di performance, io userei stringhe. E' il miglior modo di preservare l'integrità del numero in termini di storage e visualizzazione. Poi è chiaro, se vai a farci operazioni, devi comunque passare dal formato in virgola mobile.
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline wlf

  • Utente normale
  • ***
  • Post: 357
  • Respect: +8
    • Mostra profilo
  • Dispositivo Android:
    Xperia
Re:Query SQLite che restituisce risultato bizzarro!
« Risposta #4 il: 25 Luglio 2014, 12:43:03 CEST »
0
Dovendo memorizzare dei numeri in virgola mobile in un database, se non ci sono problemi "particolari" di performance, io userei stringhe. E' il miglior modo di preservare l'integrità del numero in termini di storage e visualizzazione. Poi è chiaro, se vai a farci operazioni, devi comunque passare dal formato in virgola mobile.

Probabilmente stai supponendo che nel db SQLite gli importi siano memorizzati in modo errato; ho già controllato, facendo un'estrazione del db, è perfetto, tutti gli importi hanno al max 2 decimali e ci sono anche un tot di importi interi. Quindi non credo che le stringhe possano "aiutare" se non per il fatto che io sto utilizzando una query secca che mi da un risultato, mentre con le stringhe probabilmente dovrei ciclare per sommarne una alla volta.

Sospetto pure che ciclando con gli importi lasciati numeric nel DB potrebbe darmi il risultato corretto, diversamente a quanto accade con una query secca, in questo caso il problema sarebbe da ricercare in come effettua il calcolo SQLite! ;)
Se mi forniscono ancora uno degli Smartphone che aveva il problema eventualmente ti faccio una verifica! :)


Per ora ho utilizzato un altro approccio mutuato dalle "tecniche di programmazione":

Codice (Java): [Seleziona]
        public Double getTotal() {
                Double Totale = 0;
                if (database.isOpen()) {
                        Cursor myCursor = database.query(DbHelper.DATABASE_TABLE,
                                        new String[] { "SUM(IMPDARE * 100) - SUM(IMPAVERE * 100)" }, null, null, null,
                                        null, null);
                        myCursor.moveToFirst();
                        if (myCursor.moveToFirst()) {
                                Totale = myCursor.getFloat(0);
                        }
                        myCursor.close();                      
                }
                return Totale / 100;
        }

Eventualmente potrei passare anche per un Integer, ma già così funziona correttamente. ;)