Rappresentare i valori monetari in Java

Capisco che BigDecimal è la migliore procedura consigliata per rappresentare i valori monetari in Java. Cosa usi? C’è una libreria migliore che preferisci usare invece?

BigDecimal fino in fondo. Ho sentito parlare di alcune persone che creano le proprie classi Cash o Money che incapsulano un valore in contanti con la valuta, ma sotto la pelle è ancora un BigDecimal , probabilmente con arrotondamento BigDecimal.ROUND_HALF_EVEN .

Edit: 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 vai a scavare sotto il cofano, vedrai che usano anche BigDecimal .

Può essere utile per le persone che arrivano qui dai motori di ricerca per sapere di JodaMoney: http://www.joda.org/joda-money/ .

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 libreria conveniente in cui mi sono imbattuto prima è 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 è ansible passare rapidamente se sono necessarie modifiche. Joda-Money è pubblicato sotto la licenza Apache 2.0.

Se stai usando solo dollari e centesimi, userei un lungo (offset di 2 posizioni decimali). Se hai bisogno di maggiori dettagli, grandi decimali possono essere la strada da percorrere.

Ad ogni modo, probabilmente estenderei la class per avere un .toString () che usa il formato corretto, e come posto per mettere altri metodi che potrebbero venire (per molto tempo, moltiplicando e dividendo andrà storto se il decimale non è ‘aggiustato)

Inoltre, se si utilizza definire la propria class e l’interfaccia, è ansible sostituire l’implementazione a proprio piacimento.

BigDecimal o un’altra rappresentazione a punto fisso è ciò che è generalmente necessario per soldi.

Le rappresentazioni e i calcoli a virgola mobile ( Double , Virgola mobile) non sono esatti e portano a risultati errati.

Devi essere così attento quando si tratta di tempo e denaro.

Quando lavori con i soldi, spero che tutti debbano sapere 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 long. In questo modo non hai mai a che fare con una cifra decimale.

Visualizzi solo dollari quando lo stampi. Funziona sempre con cents interni usando interi. Questo può essere complicato se è necessario dividere o utilizzare Math.abs ().

Tuttavia, potresti occuparti di mezzo centesimo o addirittura di un centesimo di un centesimo. Non so quale sia un buon modo per farlo. Potresti aver bisogno di gestire il millesimo di centesimi e usare un lungo. O forse sarai costretto a usare BigDecimal

Farei molte più letture su questo, ma ignoro tutti quelli che iniziano a parlare di usare un galleggiante o un doppio per rappresentare il denaro. Stanno solo chiedendo guai.

Sento che il mio consiglio non è completo, quindi per favore mettici dentro un po ‘di più. Hai a che fare con tipi pericolosi!

Creare una class di denaro è la strada da percorrere. Utilizzando BigDecimal (o anche un int) sotto. Quindi utilizzare la class di valuta per definire la convenzione di arrotondamento.

Sfortunatamente senza l’overloading dell’operatore, Java rende piuttosto spiacevole la creazione di tipi di base.

C’è una libreria migliore, timeandmoney . 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 raccomanda l’implementazione di una class di Money dedicata per rappresentare gli importi in valuta e implementa anche le regole per la conversione di valuta.

Ehi, ecco un articolo molto interessante su BigDecimal e un esempio illustrativo del perché a volte viene usato al posto del doppio. BigDecimal Tutorial .

È ansible utilizzare la class DecimalFormat quando alla fine viene visualizzato un valore di valuta. Fornisce supporto per la localizzazione ed è piuttosto estendibile.

Incapsulare BigDecimal nella class Money che ha anche una valuta come qualcuno menzionato sopra. L’importante è che tu faccia una quantità estrema di test unitari e soprattutto se lavori con valute diverse. Inoltre è una buona idea se aggiungi un costruttore conveniente che prende una stringa o un metodo factory che fa lo stesso in modo che tu possa scrivere i tuoi test qualcosa del genere:

  assertEquals(Money.create("100.0 USD").add("10 GBP"),Money.create("116 USD")); 

Ci sono sempre vincoli e specificità coinvolti. Chiunque non abbia esperienza sufficiente per apprezzare le sottili questioni delineate nel seguente articolo dovrebbe seriamente riconsiderare prima di affrontare i dati finanziari reali:

http://lemnik.wordpress.com/2011/03/25/bigdecimal-and-your-money

BigDecimal non è l’unica rappresentazione corretta o l’unico pezzo del puzzle. A determinate condizioni, l’utilizzo di una class Money supportata da centesimi memorizzati come numero intero potrebbe essere sufficiente e sarebbe molto più veloce di BigDecimal. Sì, ciò implica l’uso di dollari come valuta e limiti di importi ma tali vincoli sono perfettamente accettabili per molti casi d’uso e tutte le valute hanno comunque casi speciali per arrotondamenti e sottotitoli, quindi non esiste una soluzione “universale”.