Quel type de données dois-je utiliser pour la devise du jeu?

96

Dans un simple jeu de simulation d'entreprise (construit en Java + Slick2D), le montant actuel d'argent d'un joueur doit-il être stocké sous la forme d'un floatou d'un intautre élément?

Dans mon cas d'utilisation, la plupart des transactions utilisent des cents (0,50 USD, 1,20 USD, etc.), et le calcul du taux d'intérêt simple est impliqué.

J'ai vu des gens dire que vous ne devriez jamais utiliser floatpour de l'argent, ainsi que des gens qui disent que vous ne devriez jamais utiliser intpour de l'argent. Je pense que je devrais utiliser intet arrondir tout calcul de pourcentage nécessaire. Que devrais-je utiliser?

Lucas Tulio
la source
2
Cette question a été discutée sur StackOverflow. On dirait que BigDecimal est probablement la voie à suivre. stackoverflow.com/questions/285680/…
Ade Miller
2
Java n’a-t-il pas un Currencytype semblable à celui de Delphi, qui utilise des mathématiques à virgule décimale mises à l’échelle pour vous donner des calculs décimaux sans les problèmes de précision inhérents à la virgule flottante?
Mason Wheeler
1
C'est un jeu. La comptabilité ne va pas vous lyncher pour un sou arrondi et donc les raisons normales contre l’utilisation de la virgule flottante pour la monnaie importent peu.
Loren Pechtel
@MasonWheeler: Java a BigDecimalce genre de problèmes.
Martin Schröder

Réponses:

92

Vous pouvez utiliser intet considérer tout en cents. 1,20 $ ne représente que 120 cents. À l'affichage, vous mettez la décimale à l'endroit auquel elle appartient.

Les calculs d'intérêts seraient simplement tronqués ou arrondis. Alors

newAmt = round( 120 cents * 1.04 ) = round( 124.8 ) = 125 cents

De cette façon, vous n'avez pas de décimales en désordre qui traînent toujours. Vous pourriez devenir riche en ajoutant l'argent non comptabilisé (en raison d'arrondissements) à votre propre compte bancaire.

bobobobo
la source
3
Si vous utilisez roundil n'y a pas de vraie raison de jeter int, est-ce qu'il y a?
Sam Hocevar
19
+1 Les nombres en virgule flottante gâchent les comparaisons d'égalité, ils sont plus difficiles à mettre en forme correctement et introduisent des erreurs d'arrondissement amusantes au fil du temps. Il est préférable de faire tout cela vous-même pour ne pas vous plaindre plus tard. Ce n'est vraiment pas beaucoup de travail.
Dobes Vandermeer
+1 Cela semble être un bon moyen de jouer à mon jeu. Je traiterai moi-même les contours et éviterai tous les problèmes de flottement.
Lucas Tulio
Juste un avertissement: j'ai changé la réponse correcte à celle-ci parce que c'est finalement ce que j'ai utilisé. C'est beaucoup plus simple et dans le contexte d'un jeu aussi simple, les décimales non comptabilisées importent peu.
Lucas Tulio
3
Toutefois, utilisez des points de base et non des centimes (où 100 points de base = 1 cent) avec un facteur de 10 000 au lieu de 100. Cela est requis par les PCGR pour toutes les applications financières, bancaires ou comptables.
Pieter Geerkens
66

Ok, je vais sauter dedans.

Mon conseil: c'est un jeu. Prenez le facile et utilisez double.

Voici ma raison d'être:

  • floatUn problème de précision apparaît lors de l’ajout d’unités à des millions, alors, même s’il est bénin, j’éviterais ce type. doublecommence seulement à avoir des problèmes autour des quintillons (un milliard de milliards).
  • Puisque vous allez avoir des taux d'intérêt, vous aurez besoin d'une précision infinie théorique de toute façon: avec 4% des taux d'intérêt, 100 $ deviendra 104 $, puis 108,16 $, puis 112,4864 $, etc. Cela rend intet longinutile parce que vous ne savez pas où arrêter avec les décimales.
  • BigDecimalvous donnera une précision arbitraire mais deviendra péniblement lente, à moins que vous ne la fixiez à un moment donné. Quelles sont les règles d'arrondi? Comment choisissez-vous où vous arrêter? Vaut-il la peine d'avoir plus de bits de précision que double? Je ne crois pas.

La raison pour laquelle l'arithmétique en virgule fixe est utilisée dans les applications financières est parce qu'elles sont déterministes. Les règles d'arrondi sont parfaitement définies, parfois par la loi, et doivent être strictement appliquées, mais l'arrondi se produit toujours à un moment donné. Tout argument en faveur d'un type donné basé sur la précision est vraisemblablement faux. Tous les types ont des problèmes de précision avec le type de calcul que vous allez faire.

Exemples pratiques

Je vois pas mal de commentaires affirmant des choses sur l’arrondissement ou la précision avec lesquelles je ne suis pas d’accord. Voici quelques exemples supplémentaires pour illustrer ce que je veux dire.

Stockage : si votre unité de base est le cent, vous voudrez probablement arrondir au cent le plus proche lors du stockage des valeurs:

void SetValue(double v) { m_value = round(v * 100.0) / 100.0; }

Lors de l'adoption de cette méthode, vous n'aurez absolument aucun problème d'arrondi, ce que vous n'auriez pas aussi avec un type entier.

Récupération : tous les calculs peuvent être effectués directement sur les valeurs doubles, sans conversions:

double value = data.GetValue();
value = value / 3.0 * 12.0;
[...]
data.SetValue(value);

Notez que le code ci-dessus ne fonctionne pas si vous remplacez doublepar int64_t: il y aura une conversion implicite vers double, puis une troncature avec int64_t, avec une perte possible de information.data.GetValue ()

Comparaison : les comparaisons sont la seule chose à faire avec les types à virgule flottante. Je suggère d'utiliser une méthode de comparaison telle que celle-ci:

/* Are values equal to a tenth of a cent? */
bool AreCurrencyValuesEqual(double a, double b) { return abs(a - b) < 0.001; }

Arrondir l'équité

Supposons que le compte compte 9,99 $ avec un intérêt de 4%. Combien doit gagner le joueur? Avec un arrondi entier, vous obtenez 0,03 $; avec des arrondis en virgule flottante, vous obtenez 0,04 $. Je crois que ce dernier est plus juste.

sam hocevar
la source
4
+1 La seule clarification que j'aimerais ajouter, c'est que les applications financières sont conformes à des exigences prédéfinies spécifiques, tout comme l'algorithme d'arrondi. Si le jeu est un jeu de casino, il est conforme à des normes similaires et le double n'est pas une option.
Ivaylo Slavov
2
Vous devez encore penser aux règles d'arrondi pour formater l'interface utilisateur. Parce qu'il y a toujours une fraction de joueurs qui essaieront de traiter un jeu comme une feuille de calcul si vous ne voulez pas que les gens sautent sur les pieds en criant quand ils s'aperçoivent que votre arrière-plan n'utilise pas la même précision que votre interface utilisateur. résultats «erronés» étant affichés, votre meilleure option pour les garder silencieux consiste à utiliser la même représentation interne et externe, ce qui signifie utiliser un format de point fixe. À moins que les performances ne deviennent un problème, BigDecimal est le meilleur choix pour le faire.
Dan Neely
10
Je ne suis pas d'accord avec cette réponse. Les problèmes d'arrondi apparaissent et, s'ils baissent, et si vous n'utilisez pas d'arrondi supplémentaire, 1,00 $ peut devenir soudainement 0,99 $. Mais le plus important est que les décimales de précision arbitraires lentes sont (presque) totalement hors de propos. Nous sommes presque en 2013 et, à moins que vous ne fassiez des factorisations importantes, des trigonomètres ou des logarithmes sur plusieurs millions de nombres avec des milliers de chiffres, vous ne remarquerez même pas une baisse des performances. Quoi qu'il en soit, simple est toujours préférable, donc ma recommandation est de stocker tous les nombres sous forme de centimes. De cette façon, ils sont tous int_64ts.
Panda Pyjama
8
@ Sam dernière fois que j'ai vérifié mon compte bancaire, mon solde ne s'est pas terminé par .0000000000000001. Les systèmes de monnaie réelle doivent fonctionner avec des unités non divisibles, et ceci est correctement représenté avec des entiers. Si vous devez faire les divisions de devise correctement (ce qui n’est en fait pas si courant dans le monde financier réel), vous devez les faire pour que l’argent ne soit pas perdu. Par exemple 10/3 = 3+3+4ou 10/3 = 3+3+3 (+1). Pour toutes les autres opérations, les entiers fonctionnent parfaitement, contrairement à la virgule flottante qui peut poser des problèmes d'arrondi dans toutes les opérations.
Panda Pyjama
2
@SamHocevar 999 * 4/100. Lorsque cela n’est pas stipulé par la réglementation, nous supposons que tous les arrondissements seront effectués en faveur des banques.
Dan Neely
21

Les types à virgule flottante en Java ( float, double) ne sont pas une bonne représentation des devises pour une raison principale: une erreur machine lors de l'arrondi. Même si un simple calcul retourne un nombre entier - comme 12.0/2(6.0), la virgule flottante peut l’entourer de façon erronée (du fait de la représentation spécifique de ces types en mémoire) par 6.0000000000001ou 5.999999999999998ou similaire. Cela résulte de l'arrondi spécifique de la machine qui se produit dans le processeur et est propre à l'ordinateur qui l'a calculé. Habituellement, il est rarement un problème d’opérer avec ces valeurs, car l’erreur est assez négligente, mais c’est difficile de l’afficher à l’utilisateur.

Une solution possible à ce problème consisterait à utiliser une implémentation personnalisée de type de données à virgule flottante, telle que BigDecimal. Il prend en charge de meilleurs mécanismes de calcul qui isolent au moins les erreurs d'arrondi pour ne pas être spécifiques à la machine, mais sont plus lentes en termes de performances.

Si vous avez besoin d'une productivité élevée, vous feriez mieux de vous en tenir aux types simples. Si vous travaillez avec des données financières importantes et que chaque centime est important (comme une application Forex ou un jeu de casino), je vous recommanderais d'utiliser Longou long. Longvous permettrait de gérer de grandes quantités et une bonne précision. Supposons simplement que vous avez besoin, disons, de 4 chiffres après la virgule, il vous suffit de multiplier ce montant par 10000. Ayant de l'expérience dans le développement de jeux de casino en ligne, je l'ai Longsouvent vue utilisée pour représenter l'argent en cents . Dans les applications Forex, la précision est plus importante, vous aurez donc besoin d’un multiplicateur plus important. Néanmoins, les nombres entiers ne posent aucun problème d’arrondi machine (bien sûr, l’arrondissement manuel comme dans 3/2, vous devriez vous en occuper vous-même).

Une option acceptable serait d'utiliser les types de virgule flottante standard - Floatet Double, si les performances sont plus importantes que la précision au centième de cent près. Ensuite, dans votre logique d’affichage, il vous suffit d’utiliser une mise en forme prédéfinie , afin que la laideur d’un arrondi potentiel de la machine n’atteigne pas l’utilisateur.

Ivaylo Slavov
la source
4
+1 Un détail: "Supposons simplement que vous avez besoin, disons, de 4 chiffres après la virgule décimale, tout ce dont vous avez besoin est de multiplier le montant par 1000." -> Ceci s'appelle point fixe.
Laurent Couvidou
1
@ Sam, les numéros ont été fournis pour l'exemple de mise. Malgré tout, j'ai personnellement constaté des résultats étranges avec des chiffres aussi simples, mais ce n'est pas un scénario fréquent. Quand des points flottants arrivent à jouer, cela est probablement plus probable, mais plus improbable
Ivaylo Slavov
2
@ Ivaylo Slavov, je suis d'accord avec vous. Dans ma réponse, je viens de faire mon opinion. J'aime discuter et avoir la volonté de prendre la bonne chose. Merci également pour votre avis. :)
Md Mahbubur Rahman
1
@ SamHocevar: Ce raisonnement ne fonctionne pas dans tous les cas. Voir: ideone.com/nI2ZOK
Samaursa
1
@ SamHocevar: Ce n'est pas garanti non plus. Les nombres dans la plage qui sont toujours des nombres entiers commencent à accumuler des erreurs sur la première division: ideone.com/AKbR7i
Samaursa
17

Pour le jeu à petite échelle et où la vitesse de traitement, la mémoire est un problème important (en raison de la précision ou de travailler avec un calculateur mathématique peut rendre péniblement lent), il suffit de doubler .

Mais pour les jeux à grande échelle (par exemple, les jeux sociaux) et où la vitesse de traitement, la mémoire n'est pas limitée, BigDecimal est meilleur. Parce qu'ici,

  • int ou long pour les calculs monétaires.
  • les flottants et les doubles ne peuvent pas représenter avec précision la plupart des nombres réels de base 10.

Ressources:

De https://stackoverflow.com/questions/3730019/why-not-use-double-or-float-to-represent-currency

Parce que les flottants et les doubles ne peuvent pas représenter avec précision la plupart des nombres réels de base 10.

Voici comment fonctionne un nombre à virgule flottante IEEE-754: il dédie un bit pour le signe, quelques bits pour stocker un exposant et le reste pour la fraction réelle. Cela conduit à des nombres représentés sous une forme similaire à 1.45 * 10 ^ 4; sauf qu'au lieu que la base soit 10, c'est deux.

En fait, tous les nombres décimaux réels peuvent être vus comme des fractions exactes d'une puissance de dix. Par exemple, 10h45 est vraiment 1045/10 ^ 2. Et de même que certaines fractions ne peuvent pas être représentées exactement comme une fraction d'une puissance de dix (1/3 me vient à l'esprit), certaines ne peuvent pas l'être exactement comme une fraction d'une puissance de deux. Par exemple, vous ne pouvez tout simplement pas stocker 0,1 dans une variable à virgule flottante. Vous obtiendrez la valeur représentable la plus proche, qui est quelque chose comme 0.099999999999999999996, et le logiciel l'arrondira à 0.1 lors de son affichage.

Cependant, à mesure que vous effectuez des additions, des soustractions, des multiplications et des divisions sur des nombres inexacts, vous perdrez de plus en plus de précision au fur et à mesure de l'addition des petites erreurs. Cela rend les flottants et les doubles inadéquats pour traiter de l'argent, où une précision parfaite est requise.

De Bloch, J., Effective Java, 2 e éd., Article 48:

The float and double types are particularly ill-suited for 

calculs monétaires car il est impossible de représenter 0,1 (ou toute autre puissance négative de dix) sous forme de float ou de double exactement.

For example, suppose you have $1.03 and you spend 42c. How much money do you have left?

System.out.println(1.03 - .42);

prints out 0.6100000000000001.

The right way to solve this problem is to use BigDecimal, 

int ou long pour les calculs monétaires.

Regardez aussi

Md Mahbubur Rahman
la source
Je suis seulement en désaccord avec la partie qui convient aux petits calculs. Dans mon expérience réelle, il s'est avéré suffisant pour gérer une bonne précision et de grosses sommes d'argent. Oui, cela peut paraître un peu lourd à utiliser, mais il bat BigDecimal en deux points cruciaux - 1) il est plus rapide (BigDecimal utilise l’arrondi logiciel, ce qui est bien plus lent que l’arrondi intégré de la CPU utilisé dans float / double) et 2) BigDecimal est plus difficile à conserver dans une base de données sans perte de précision - toutes les bases de données ne prennent pas en charge un tel type "personnalisé". Long est bien connu et largement supporté par toutes les bases de données majeures.
Ivaylo Slavov
@ Ivaylo Slavov, désolé pour mon erreur. J'ai mis à jour ma réponse.
Md Mahbubur Rahman
Aucune excuse nécessaire pour donner une approche différente pour le même problème :)
Ivaylo Slavov
2
@ Ivaylo Slavov, je suis d'accord avec vous. Dans ma réponse, je viens de faire mon opinion. J'aime discuter et avoir la volonté de prendre la bonne chose. Merci également pour votre avis. :)
Md Mahbubur Rahman
L’objet de ce site est de clarifier les problèmes et d’aider le PO à prendre la bonne décision, en fonction du scénario. Tout ce que nous pouvons faire, c'est aider à accélérer le processus :)
Ivaylo Slavov
13

Vous voulez stocker votre monnaie longet calculer votre monnaie double, au moins comme une sauvegarde. Vous voulez que toutes les transactions aient lieu comme long.

La raison pour laquelle vous souhaitez stocker votre devise longest que vous ne voulez pas perdre de devise.

Supposons que vous utilisiez un double, et que vous n’ayez pas d’argent. Quelqu'un vous donne trois centimes, puis les reprend.

You:       0.1+0.1+0.1-0.1-0.1-0.1 = 2.7755575615628914E-17

Eh bien, ce n'est pas si cool. Peut-être que quelqu'un avec 10 $ veut donner sa fortune en vous donnant d'abord trois centimes, puis en donnant 9,70 $ à quelqu'un d'autre.

Them: 10.0-0.1-0.1-0.1-9.7 = 1.7763568394002505E-15

Et puis vous leur rendez les dix sous:

Them: ...+0.1+0.1+0.1 = 0.3000000000000018

Ceci est juste cassé.

Utilisons maintenant un long terme, et nous garderons une trace des dixièmes de centimes (donc 1 = 0,001 $). Donnons à chacun sur la planète un milliard, cent douze millions, soixante quinze mille mille cent quarante trois dollars:

Us: 7000000000L*1112075143000L = 1 894 569 218 048

Euh, attendez, on peut donner à tout le monde plus d'un milliard de dollars, et ne dépenser qu'un peu plus de deux? Le débordement est une catastrophe ici.

Ainsi, chaque fois que vous calculez une somme d’argent à transférer, utilisez-la doubleet Math.roundobtenez-la long. Puis corrigez les soldes (ajoutez et soustrayez les deux comptes) en utilisant long.

Votre économie ne coulera pas et atteindra un quadrillion de dollars.

Il ya plus de problèmes épineux - par exemple, que faites-vous si vous effectuez 20 paiements? * - mais cela devrait vous aider à démarrer.

* Vous calculez ce qu'est un paiement, arrondissez à long; puis multiplier par 20.0et vérifier qu'il est dans la fourchette; Dans ce cas, multipliez le paiement par 20Lpour obtenir le montant déduit de votre solde. En général, toutes les transactions doivent être traitées comme longsi, de sorte que vous avez vraiment besoin de résumer toutes les transactions individuelles; vous pouvez multiplier comme un raccourci, mais vous devez vous assurer de ne pas ajouter des erreurs d' arrondi et que vous ne déborde pas, ce qui signifie que vous devez vérifier avec doubleavant de faire le calcul réel long.

Rex Kerr
la source
8

J'irais jusqu'à dire que toute valeur pouvant être affichée à l'utilisateur devrait presque toujours être un entier. L'argent n'en est que l'exemple le plus marquant. Infliger 225 dégâts à quatre reprises à un monstre de 900 CV et constater qu'il lui reste 1 HP restera soustrait à l'expérience, tout autant que de constater que vous êtes une fraction invisible d'un centime de moins.

Sur le plan plus technique, je pense qu’il est intéressant de noter qu’il n’est pas nécessaire de recourir à des actions flottantes pour faire des choses avancées comme l’intérêt. Tant que vous avez suffisamment de marge dans le type entier choisi, une multiplication et une division remplacent une multiplication par un nombre décimal, par exemple, pour ajouter 4%, arrondi à la valeur inférieure:

number=(number*104)/100

Pour ajouter 4%, arrondi par les conventions standard:

number=(number*104+50)/100

Ici, pas d’imprécision, les arrondis se divisant toujours exactement sur la .5marque.

Edit, la vraie question:

Voyant à quel point le débat est parti , je commence à penser que la question décrivant ce que est tout au sujet peut être plus utile qu'un simple int/ floatréponse. Au coeur de la question, il ne s'agit pas de types de données, mais de contrôler les détails d'un programme.

L'utilisation d'un entier pour représenter une valeur non entière oblige le programmeur à traiter les détails de la mise en œuvre. "Quelle précision utiliser?" et "Quelle manière de tourner?" sont des questions auxquelles il faut répondre explicitement.

Un float par contre ne force pas le programmeur à s’inquiéter, il fait déjà à peu près tout ce à quoi on pourrait s’attendre. Mais comme un flotteur n’est pas une précision infinie, il se produira des arrondis, et ces arrondis sont assez imprévisibles.

Que se passe-t-il dans une utilisation flotte et veut contrôler l'arrondi? Cela s'avère presque impossible. Le seul moyen de rendre un flottant réellement prévisible est d'utiliser uniquement des valeurs pouvant être représentées dans un entier 2^n. Mais cette construction rend les flotteurs assez difficiles à utiliser.

La réponse à la question simple est donc la suivante: si vous voulez prendre le contrôle, utilisez des entiers, sinon utilisez des flottants.

Mais la question débattue n’est qu’une autre forme de la question: voulez-vous prendre le contrôle?

aaaaaaaaaaaa
la source
5

Même si c'est "seulement un jeu", j'utiliserais Money Pattern de Martin Fowler, appuyé par un long.

Pourquoi?

Localisation (L10n): en utilisant ce modèle, vous pouvez facilement localiser la devise de votre jeu. Pensez aux vieux jeux de magnats comme "Transport Tycoon". Ils permettent facilement au joueur de changer la monnaie du jeu (par exemple, de la livre sterling au dollar américain) pour rencontrer la monnaie du monde réel.

Et

Le type de données long est un entier de complément à deux signé de 64 bits. Il a une valeur minimale de -9 223 372 036 854 775 808 et une valeur maximale de 9 223 372 036 854 775 807 (inclus) ( tutoriels Java )

Cela signifie que vous pouvez stocker 9 000 fois la masse monétaire actuelle de M2 ​​US (environ 10 000 milliards de dollars). Vous laissant assez de place pour utiliser n'importe quelle autre devise mondiale, probablement même ceux qui ont / ont eu une hyperinflation (Si curieux, voir l'inflation allemande après la Première Guerre mondiale , où 1 livre de pain représentait 3 000 000 000 de marks)

Long est facile à conserver, très rapide et devrait vous laisser assez de temps pour faire tous les calculs d'intérêts en utilisant uniquement des arithmétiques entiers, réponse de eBusiness donne une explication sur la façon de procéder.

grprado
la source
2

Combien de travail voulez-vous mettre à ce sujet? Quelle est l'importance de la précision? Vous souciez-vous de suivre les erreurs fractionnelles qui se produisent avec l'arrondi et l'imprécision de la représentation des nombres décimaux dans un système binaire?

En fin de compte, j'ai tendance à passer un peu plus de temps à coder et à mettre en œuvre des tests unitaires pour les "cas critiques" et les cas problématiques connus - je penserais donc à un BigInteger modifié qui englobe des quantités arbitrairement grandes et conserve les bits fractionnels avec un BigDecimal ou une partie BigRational (deux BigIntegers, un pour le dénominateur et une autre pour le numérateur) - et incluez du code pour conserver la partie fractionnelle en tant que fraction réelle en ajoutant (peut-être seulement périodiquement) toute partie non fractionnaire au BigInteger principal. Ensuite, je garderais un suivi interne de tout ce qui était en cents, juste pour garder les parties fractionnaires en dehors des calculs de l'interface graphique.

Probablement trop complexe pour un (simple) jeu - mais bon pour une bibliothèque publiée en open source! Nous aurions juste besoin de trouver des moyens de conserver de bonnes performances lorsque nous traitons les bits fractionnaires ...

Richard Arnold Mead
la source
1

Certainement pas flotter. Avec seulement 7 chiffres, vous n’avez que la précision suivante:

12 345,67 123 456,7x

Vous voyez donc qu'avec déjà 10 ^ 5 dollars, vous perdez la trace de quelques centimes. double est utilisable pour le jeu, pas dans la vie réelle pour des raisons de précision.

Mais long (et par là, je veux dire 64 bits, ou long en C ++) ne suffit pas si vous voulez suivre les transactions et les résumer. Il suffit de maintenir les avoirs nets de toute entreprise, mais toutes les transactions d'un an risquent de déborder. Cela dépend de la taille de votre "monde" financier.

Dov
la source
0

Une autre solution que j'ajouterai ici est de créer une classe monétaire. La classe serait quelque chose comme (pourrait même simplement être une structure).

class Money
{
     string currencyType; //the type of currency example USD could be an enum as well
     bool isNegativeValue;
     unsigned long int wholeUnits;
     unsigned short int partialUnits;
}

Cela vous permettrait de représenter les centimes dans ce cas sous forme d'entier et les dollars entiers sous forme d'entier. Puisque vous avez un indicateur distinct pour être négatif, vous pouvez utiliser des entiers non signés pour vos valeurs, ce qui double le montant possible (vous pouvez également écrire une classe de nombres qui applique cette idée aux nombres pour obtenir des nombres VRAIMENT grands). Tout ce que vous devez faire est de surcharger les opérateurs mathématiques et vous pouvez l'utiliser comme n'importe quel type de données. Cela prend plus de mémoire, mais cela élargit vraiment les limites de valeur.

Cela pourrait être étendu pour inclure des éléments tels que le nombre d'unités partielles par unités entières afin que vous puissiez avoir des devises subdivisées sur autre chose que 100 sous-unités, dans ce cas, cents par dollar. Vous pourriez avoir 125 flops par exemple un floper.

Modifier:

J'élargirai l'idée en ce sens que vous pourriez également avoir une table de correspondance, à laquelle la classe monétaire peut avoir accès, qui fournirait un taux de change pour sa devise par rapport à toutes les autres devises. Vous pouvez intégrer cela dans les fonctions de surcharge de votre opérateur. Par conséquent, si vous essayez automatiquement d'ajouter 4 USD à 4 £ britanniques, cela vous donnera automatiquement 6,6 livres (au moment de l'écriture).

Azaral
la source
0

Comme mentionné dans l'un des commentaires sur votre question initiale, ce problème a été couvert dans StackExchange: https://stackoverflow.com/questions/8148684/what-is-the-best-data-type-to-use-for- money-in-java-app

Fondamentalement, les types à virgule flottante ne doivent jamais être utilisés pour représenter des devises et, comme la plupart des langages, Java a un type plus approprié. La propre documentation d'Oracle sur les primitives suggère d'utiliser BigDecimal .

FlintZA
la source
-1

Utilisez la classe c'est la meilleure façon. Vous pouvez masquer la mise en œuvre de votre argent, vous pouvez basculer le double / long tout ce que vous voulez à tout moment.

Exemple

class Money
{
    private long count;//Store here what ever you want in what type you want i suggest long or int
    //methods constructors etc.
    public String print()
    {
        return count/100.F; //convert this to string
    }
}

Dans votre code, utilisez simplement le getter, c’est une meilleure façon de penser et vous pouvez stocker des méthodes plus utiles.

Dawid Drozd
la source