Infocurci - programmatore Php Roma
Infocurci - programmatore Php Roma
Questo sito non lascia nessun cookie sul vostro pc, consuma pochissimi kb, non profila nulla e non raccoglie dati personali. Siete i benvenuti.

Mysql : Problemi di arrotondamento database

I campi di tipo FLOAT sono spesso usati per memorizzare dati numerici. In realtà questo campo soffre di un particolare problema che può portare a risultati inattesi. Ecco perché preferire tipo Decimal o Numeric.

Mysql

Prendete un database mysql, inserite in una tabella un campo FLOAT ed inserite due record di prova, mettendo in uno un valore intero ed in uno un valore a due decimali, ad esempio 94 e 84.26.

Ora fate restituire al database questi valori, moltiplicati per 1:

select numero, (numero *1) as numero_test from tabella:

sembra una query banale e scontata ma il risultato è sorprendente:

94|94
84.26|84,26000213623047

Questo comportamento non accade ovviamente solo in query cosi banali, ma anche in query con le quali abbiamo a che fare tutti i giorni dove magari il campo in questione è la base per il calcolo di spese di spedizione di un'ecommerce e viene moltiplicato per il numero di pezzi acquistati.

Vi lascio immaginare poi cosa succede in query di selezione:

select * from tabella where numero=84.26

non trova nessun record. Come mai?
Il problema risiede nello standard IEEE 754 che memorizza i numeri in virgola mobile in formato base 2; questo porta a comportamenti diversi dai numeri memorizzati in decimale. Un numero come 84.26 richiede una precisione infinita in binario, cosa non consentita in campi Float e quindi viene memorizzato il valore in base 2 più vicino. Da qui la differenza di valori memorizzata nella tabella.

La soluzione è quella di usare campi di tipo NUMERIC (o DECIMAL, sono praticamente identici) dove viene memorizzato il valore fino alla precisione che specifichiamo quando creiamo il campo.

Un campo DECIMAL(15,4) significa ad esempio che il campo conterrà 15 cifre, di cui 11 per la parte intera e 4 per la parte dopo la virgola.