NUMERIC
/DECIMAL
Come ha detto Joachim Isaksson
, desideri utilizzare NUMERIC
/DECIMAL
type, come un tipo di precisione arbitraria.
Due punti importanti su NUMERIC
/DECIMAL
:
- Leggi il doc attentamente per imparare che dovresti specificare la scala per evitare la scala predefinita di 0, che significa valori interi in cui la frazione decimale viene tagliata. Anche se questo è uno dei luoghi in cui Postgres si allontana dall'SQL standard (dandoti qualsiasi scalabilità fino al limite di implementazione). Quindi non specificare la scala è una scelta sbagliata.
- I tipi SQL
NUMERIC
&DECIMAL
sono vicini ma non identici secondo lo standard SQL. In SQL:92 , la precisione specificata perNUMERIC
è rispettato, mentre perDECIMAL
il server di database può aggiungere ulteriore precisione oltre a quanto specificato. Anche in questo caso Postgres si discosta un po' dallo standard, con entrambiNUMERIC
&DECIMAL
documentato come equivalente.
Termini:
- La precisione è il numero totale di cifre in un numero.
- La scala è il numero di cifre a destra del punto decimale (la frazione decimale).
- ( Precisione - Scala ) =Numero di cifre a sinistra della virgola decimale (parte intera).
Sii chiaro sulle specifiche del tuo progetto in termini di precisione e scala:
- Grande
La precisione deve essere sufficientemente grande per gestire numeri più grandi che potrebbero essere necessari in futuro. Significato... Forse la tua app oggi funziona per importi di migliaia di USD, ma in futuro dovrà eseguire rapporti cumulativi che finiscono per milioni. - Piccolo
Per alcuni scopi contabili, potrebbe essere necessario memorizzare una frazione dell'importo in valuta più piccolo. Significato... Più di 3 o 4 cifre decimali anziché le 2 necessarie per un centesimo in USD .
Evita MONEY
digita
Postgres offre un MONEY
digitare pure. Potrebbe sembrare giusto, ma probabilmente non è il migliore per la maggior parte degli scopi. Uno svantaggio è quello con MONEY
la scala è impostata da un'impostazione di configurazione a livello di database basato su locale
. In modo che l'impostazione possa variare pericolosamente facilmente quando si cambia server o si apportano altre modifiche. Inoltre, non puoi controllare quell'impostazione per colonne specifiche, mentre puoi impostare la scala su ciascuna colonna di NUMERIC
genere. Infine, MONEY
non è SQL standard come mostrato in questo elenco di dati SQL standard tipi
. Postgres include MONEY
per la comodità della gente che porta i dati da altri sistemi di database.
Sposta il punto decimale
Un'altra alternativa utilizzata da alcuni è spostare il punto decimale e archiviare semplicemente un tipo di dati intero grande.
Ad esempio, se si archivia USD dollari per centesimo, moltiplica un dato numero frazionario per 100, trasformalo in un tipo intero e procedi. Ad esempio, $ 123,45 diventa il numero intero 12.345.
Il vantaggio di questo approccio sono i tempi di esecuzione più rapidi. Operazioni come sum
sono molto veloci se eseguiti su numeri interi. Un altro vantaggio per gli interi è un minore utilizzo della memoria.
Trovo questo approccio fastidioso, confuso e rischioso. Fastidioso perché i computer dovrebbero funzionare per noi, non contro di noi. Rischioso perché alcuni programmatori o utenti potrebbero trascurare di moltiplicare/dividere per riconvertire in numero frazionario, dando risultati errati. Se si lavora in un sistema senza un buon supporto per numeri frazionari accurati, questo approccio potrebbe essere una soluzione alternativa accettabile.
Non vedo alcun vantaggio nello spostare la virgola decimale quando abbiamo DECIMAL
/NUMERIC
in SQL e BigDecimal
in Java.
Arrotondamento &NaN
Nella programmazione della tua app, così come in qualsiasi calcolo effettuato sul lato server di Postgres, fai molta attenzione e fai attenzione agli arrotondamenti e ai troncamenti nella frazione decimale. E verifica la presenza di NaN spuntando.
In entrambe le parti, app e Postgres, evita sempre virgola mobile tipi di dati per il lavoro di denaro. La virgola mobile è progettata per la velocità delle prestazioni , ma a prezzo dell'accuratezza . I calcoli possono comportare cifre extra apparentemente folli nella frazione decimale. Non va bene per scopi finanziari/denaro o altri scopi in cui l'accuratezza è importante.
BigDecimal
Sì, in Java, vuoi BigDecimal
come tipo di precisione arbitraria. BigDecimal
è più lento e utilizza più memoria, ma memorizzerà accuratamente i tuoi importi di denaro. SQL NUMERIC
/DECIMAL
dovrebbe essere mappato su BigDecimal
come discusso qui
e su StackOverflow
.
BigDecimal
è una delle cose migliori di Java. Non conosco nessun'altra piattaforma con una classe simile, in particolare una così ben implementata e perfezionata con importanti miglioramenti e correzioni apportate nel corso degli anni.
Usando BigDecimal
è decisamente più lento rispetto all'utilizzo di tipi a virgola mobile di Java
, float
&double
. Ma nelle app del mondo reale dubito che i tuoi calcoli sul denaro rappresenteranno un collo di bottiglia. E inoltre, cosa volete voi o i vostri clienti:il più veloce calcoli di denaro o accurati calcoli di denaro? 😉
Ho sempre pensato a BigDecimal
come la più grande funzionalità dormiente in Java, il vantaggio più importante dell'utilizzo della piattaforma Java su così tante altre piattaforme prive di un supporto così sofisticato per i numeri frazionari.
Domanda simile:Miglior tipo di dati per valuta