web-dev-qa-db-fra.com

Représenter les valeurs monétaires dans Java

Je comprends que BigDecimal est la meilleure pratique recommandée pour représenter les valeurs monétaires en Java. Qu'est ce que tu utilises? Y a-t-il une meilleure bibliothèque que vous préférez utiliser à la place?

91
dshaw

BigDecimal jusqu'au bout. J'ai entendu parler de certaines personnes créant leurs propres classes Cash ou Money qui encapsulent une valeur monétaire avec la devise, mais sous la peau c'est toujours un BigDecimal, probablement avec - BigDecimal.ROUND_HALF_EVEN arrondi.

Edit: Comme Don le mentionne dans sa réponse , il existe des projets open source comme timeandmoney , et alors que je les applaudis pour avoir essayé d'empêcher les développeurs d'avoir à réinventer la roue, je n'ai tout simplement pas assez confiance en une bibliothèque pré-alpha pour l'utiliser dans un environnement de production. De plus, si vous creusez sous le capot, vous verrez ils utilisent aussi BigDecimal .

76
ninesided

Il peut être utile aux personnes arrivant ici par les moteurs de recherche de connaître JodaMoney: http://www.joda.org/joda-money/ .

50

Je n'exprime pas mon opinion ici, mais il y a de très bons arguments contre BigDecimal que quelqu'un devrait probablement jeter:

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

14
orbfish

Une bibliothèque pratique que j'ai rencontrée plus tôt est la bibliothèque Joda-Money . Une de ses implémentations est en effet basée sur BigDecimal. Il est basé sur la spécification ISO-4217 pour les devises et peut prendre en charge une liste de devises personnalisée (chargée via CVS).

Cette bibliothèque contient un petit nombre de fichiers que l'on peut parcourir rapidement si des modifications sont nécessaires. Joda-Money est publié sous la licence Apache 2.0.

8
Bashar

Si vous utilisez uniquement des dollars et des cents, j'utiliserais un long (compensé par 2 décimales). Si vous avez besoin de plus de détails, une grande décimale peut être la voie à suivre.

Quoi qu'il en soit, j'étendrais probablement la classe pour avoir un .toString () qui utilise le format correct, et comme un endroit pour mettre d'autres méthodes qui pourraient apparaître (pour une longue, la multiplication et la division iront mal si la décimale n'est pas pas ajusté)

De plus, si vous utilisez définir votre propre classe et interface, vous pouvez remplacer l'implémentation à volonté.

7
Bill K

BigDecimal ou une autre représentation en virgule fixe est ce qui est généralement nécessaire pour l'argent.

Les représentations et calculs en virgule flottante (Double, Float) sont inexacts, ce qui conduit à des résultats erronés.

3
Ken Gentle

Il y a une meilleure bibliothèque, timeandmoney . OMI, il est de loin supérieur aux bibliothèques fournies par le JDK pour représenter ces 2 concepts.

2
Dónal

La création d'une classe Money est la voie à suivre. Utilisation de BigDecimal (ou même d'un int) en dessous. Ensuite, utilisez la classe Currency pour définir la convention d'arrondi.

Malheureusement, sans surcharge de l'opérateur Java, il est assez désagréable de créer de tels types de base.

2
Kozyarchuk

Vous devez être très prudent face au temps et à l'argent.

Lorsque vous travaillez avec de l'argent, j'espère que tout le monde devrait savoir qu'il ne faut jamais utiliser un flotteur ou un double.

Mais je ne suis pas sûr de BigDecimal.

Dans la plupart des cas, tout ira bien si vous gardez simplement une trace de cents dans un entier ou long. De cette façon, vous ne traitez jamais avec une décimale.

Vous affichez uniquement des dollars lorsque vous l'imprimez. Toujours travailler avec des cents internes en utilisant des entiers. Cela peut être délicat si vous avez besoin de diviser ou d'utiliser Math.abs ().

Cependant, vous pourriez vous soucier d'un demi-centime, voire d'un centième de cent. Je ne sais pas quelle est la bonne façon de procéder. Vous pourriez avoir juste besoin de gérer un millième de cents et d'utiliser une longue. Ou peut-être serez-vous obligé d'utiliser BigDecimal

Je ferais beaucoup plus de lecture à ce sujet, mais ignorez tous ceux qui commencent à parler d'utiliser un flotteur ou un double pour représenter l'argent. Ils demandent juste des ennuis.

Je sens que mes conseils ne sont pas complets, alors s'il vous plaît, mettez-y davantage. Vous avez affaire à des types dangereux!

2
Pyrolistical

Hé, voici un article très intéressant sur BigDecimal, et un exemple illustrant pourquoi parfois il est utilisé à la place des doubles. Tutoriel BigDecimal .

1
arg20

Certainement pas BigDecimal. Il y a tellement de règles spéciales pour l'arrondi et la présentation dont vous devez vous soucier.

Martin Fowler recommande la mise en œuvre d'une classe Money dédiée pour représenter les montants en devises, et qui met également en œuvre des règles de conversion des devises.

1
lindelof

Vous pouvez utiliser la classe DecimalFormat lors de l'affichage final d'une valeur monétaire. Il fournit un support de localisation et est assez extensible.

0
myanswer

Il y a toujours des contraintes et des spécificités impliquées. Quiconque sans expérience suffisante pour apprécier les questions subtiles décrites dans l'article suivant devrait sérieusement reconsidérer avant de traiter des données financières réelles:

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

BigDecimal n'est guère la seule représentation correcte ou la seule pièce du puzzle. Dans certaines conditions, l'utilisation d'une classe Money soutenue par des cents stockés sous forme d'entier pourrait être suffisante et serait beaucoup plus rapide que BigDecimal. Oui, cela implique l'utilisation de dollars comme monnaie et limite les montants, mais de telles contraintes sont parfaitement acceptables pour de nombreux cas d'utilisation et toutes les devises ont des cas spéciaux pour l'arrondissement et les sous-dénominations de toute façon, il n'y a donc pas de solution "universelle".

0
Craig

J'encapsulerais BigDecimal dans la classe Money qui a également une devise comme quelqu'un mentionné ci-dessus. L'important est que vous fassiez une quantité extrême de tests unitaires et surtout si vous travaillez avec différentes devises. C'est aussi une bonne idée si vous ajoutez un constructeur convinient qui prend une chaîne ou une méthode d'usine qui fait de même afin que vous puissiez écrire vos tests quelque chose comme ceci:

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