Capisco che BigDecimal è la best practice consigliata per rappresentare i valori monetari in Java. Cosa usi? Esiste una libreria migliore che preferisci utilizzare?
Capisco che BigDecimal è la best practice consigliata per rappresentare i valori monetari in Java. Cosa usi? Esiste una libreria migliore che preferisci utilizzare?
Risposte:
BigDecimal
fino in fondo. Ho sentito di alcune persone che creano le proprie Cash
o Money
classi che incapsulano un valore in contanti con la valuta, ma sotto la pelle è ancora un BigDecimal
, probabilmente con BigDecimal.ROUND_HALF_EVEN
arrotondamento.
Modifica: come Don menziona nella sua risposta , ci sono progetti open source come timeandmoney , e mentre li applaudo per aver cercato di impedire agli sviluppatori di dover reinventare la ruota, non ho abbastanza fiducia in una libreria pre-alpha da usare in un ambiente di produzione. Inoltre, se scavi sotto il cofano, vedrai che usano BigDecimal
anche loro .
Può essere utile per le persone che arrivano qui dai motori di ricerca per conoscere JodaMoney: http://www.joda.org/joda-money/ .
BigDecimal
sotto il cofano!
Non sto esprimendo la mia opinione qui, ma ci sono argomenti abbastanza buoni contro BigDecimal che qualcuno dovrebbe probabilmente buttare fuori:
http://lemnik.wordpress.com/2011/03/25/bigdecimal-and-your-money/
Una comoda libreria in cui mi sono imbattuto in precedenza è la libreria Joda-Money . Una delle sue implementazioni è infatti basata su BigDecimal. Si basa sulla specifica ISO-4217 per le valute e può supportare un elenco di valute personalizzato (caricato tramite CVS).
Questa libreria ha un numero limitato di file che è possibile consultare rapidamente se sono necessarie modifiche. Joda-Money è pubblicato con la licenza Apache 2.0.
Se stai usando solo dollari e centesimi, userei un long (offset di 2 cifre decimali). Se hai bisogno di maggiori dettagli, il decimale grande potrebbe essere la strada da percorrere.
Ad ogni modo, probabilmente estenderei la classe per avere un .toString () che utilizza il formato corretto e come luogo in cui inserire altri metodi che potrebbero emergere (per molto tempo, la moltiplicazione e la divisione andranno storte se il decimale non è non è aggiustato)
Inoltre, se si utilizza definire la propria classe e interfaccia, è possibile sostituire l'implementazione a piacimento.
BigDecimal
o un'altra rappresentazione a punto fisso è ciò che è generalmente necessario per il denaro.
Le rappresentazioni e i calcoli in virgola mobile ( Double
, Float
) non sono esatti e portano a risultati errati.
Devi stare molto attento quando hai a che fare con tempo e denaro.
Quando lavori con i soldi, spero che tutti sappiano di non usare mai un galleggiante o un doppio.
Ma non sono sicuro di BigDecimal.
Nella maggior parte dei casi starai bene se tieni traccia dei centesimi in un int o in un lungo. In questo modo non hai mai a che fare con una cifra decimale.
Visualizzi solo i dollari quando lo stampi. Lavora sempre con i centesimi interni usando numeri interi. Questo può essere complicato se è necessario dividere o utilizzare Math.abs ().
Tuttavia, potrebbe interessarti mezzo centesimo, o anche un centesimo di centesimo. Non so quale sia un buon modo per farlo. Potrebbe essere necessario gestire solo il millesimo di centesimi e utilizzare un lungo. O forse sarai costretto a usare BigDecimal
Vorrei leggere molto di più su questo, ma ignora tutti coloro che iniziano a parlare di usare un galleggiante o un doppio per rappresentare il denaro. Chiedono solo guai.
Sento che il mio consiglio non è completo, quindi per favore mettici di più. Hai a che fare con tipi pericolosi!
Creare una classe Money è la strada da percorrere. Utilizzando BigDecimal (o anche un int) sotto. Quindi utilizzando la classe Currency per definire la convenzione di arrotondamento.
Sfortunatamente, senza l'overload da parte dell'operatore di Java, creare tipi di base di questo tipo è piuttosto sgradevole.
C'è una libreria migliore, tempo e denaro . IMO, è di gran lunga superiore alle librerie fornite dal JDK per rappresentare questi 2 concetti.
Sicuramente non BigDecimal. Ci sono così tante regole speciali per l'arrotondamento e la presentazione di cui devi preoccuparti.
Martin Fowler consiglia l'implementazione di una classe Money dedicata per rappresentare gli importi in valuta e che implementa anche le regole per la conversione di valuta.
Ehi, ecco un articolo molto interessante su BigDecimal e un esempio illustrativo del motivo per cui a volte viene utilizzato al posto dei doppi. Tutorial BigDecimal .
È possibile utilizzare la classe DecimalFormat quando alla fine si visualizza un valore di valuta. Fornisce supporto per la localizzazione ed è abbastanza estensibile.
Incapsulerei BigDecimal nella classe Money che ha anche una valuta proprio come qualcuno menzionato sopra. La cosa importante è che tu faccia una quantità estrema di unit test e soprattutto se lavori con valute diverse. Inoltre è una buona idea se aggiungi un costruttore conveniente che accetta una stringa o un metodo factory che fa lo stesso in modo che tu possa scrivere i tuoi test in questo modo:
assertEquals(Money.create("100.0 USD").add("10 GBP"),Money.create("116 USD"));
Ci sono sempre vincoli e specifiche coinvolte. Chiunque non abbia esperienza sufficiente per apprezzare le sottili questioni delineate nel seguente articolo dovrebbe riconsiderare seriamente prima di trattare i dati finanziari del mondo reale:
http://lemnik.wordpress.com/2011/03/25/bigdecimal-and-your-money
BigDecimal non è certo l'unica rappresentazione corretta o l'unico pezzo del puzzle. Date alcune condizioni, l'utilizzo di una classe Money supportata da centesimi memorizzati come numero intero potrebbe essere sufficiente e sarebbe molto più veloce di BigDecimal. Sì, ciò implica l'uso del dollaro come valuta e limita gli importi, ma tali vincoli sono perfettamente accettabili per molti casi d'uso e tutte le valute hanno comunque casi speciali per arrotondamenti e sottodenominazioni, quindi non esiste una soluzione "universale".