Stocker de l’argent dans une colonne décimale – quelle précision et quelle échelle?

J’utilise une colonne décimale pour stocker des valeurs monétaires sur une firebase database et je me demandais aujourd’hui quelle précision et quelle échelle utiliser.

Étant donné que les colonnes supposées de caractère d’une largeur fixe sont plus efficaces, je pensais que la même chose pourrait être vraie pour les colonnes décimales. Est-ce?

Et quelle précision et quelle échelle dois-je utiliser? Je pensais à la précision 24/8. Est-ce excessif, pas assez ou ok?


C’est ce que j’ai décidé de faire:

  • Stocker les taux de conversion (le cas échéant) dans la table de transaction elle-même, comme un flottant
  • Stocker la devise dans la table de compte
  • Le montant de la transaction sera un DECIMAL(19,4)
  • Tous les calculs utilisant un taux de conversion seront traités par mon application, donc je garde le contrôle des problèmes d’arrondi

Je ne pense pas qu’un flottant pour le taux de conversion est un problème, car il est principalement destiné à la référence, et je vais tout de même le décliner.

Merci à tous pour votre précieuse consortingbution.

Si vous êtes à la recherche d’une solution unique, DECIMAL(19, 4) est un choix populaire. Je pense que cela provient de l’ancien type de données VBA / Access / Jet Currency, étant le premier type décimal à virgule fixe dans la langue; Decimal n’est venu que dans le style ‘version 1.0’ (c’est-à-dire pas complètement implémenté) dans VB6 / VBA6 / Jet 4.0.

La règle de base pour le stockage des valeurs décimales à virgule fixe consiste à stocker au moins une décimale de plus que ce dont vous avez besoin pour arrondir. Une des raisons pour lesquelles l’ancien type de Currency DECIMAL(19, 4) avec le type DECIMAL(19, 4) était que Currency affichait par nature l’arrondi des banquiers, tandis que DECIMAL(p, s) arrondi par troncature.

Une décimale supplémentaire dans le stockage pour DECIMAL permet d’implémenter un algorithme d’arrondi personnalisé plutôt que de prendre la valeur par défaut du fournisseur (et l’arrondi des banquiers est pour le moins alarmant pour un concepteur s’attendant à ce que toutes les valeurs se terminant par 0,5 soient arrondies à zéro) ).

Oui, DECIMAL(24, 8) me semble exagéré. La plupart des devises sont cotées à quatre ou cinq décimales. Je connais des situations où une échelle décimale de 8 (ou plus) est requirejse, mais où un montant monétaire «normal» (par exemple, quatre décimales) a été calculé au prorata, ce qui implique que la précision décimale doit être réduite en conséquence. un type à virgule flottante dans de telles circonstances). Et personne n’a autant d’argent aujourd’hui pour exiger une précision décimale de 24 🙂

Cependant, plutôt qu’une approche unique, certaines recherches peuvent être en cours. Demandez à votre concepteur ou à votre expert de domaine les règles comptables applicables: GAAP, EU, etc. Je rappelle vaguement certains transferts intra-étatiques de l’UE avec des règles explicites pour arrondir à cinq décimales, donc utiliser DECIMAL(p, 6) pour le stockage. Les comptables semblent généralement privilégier quatre décimales.


PS Evitez le type de données MONEY SQL Server car il présente de sérieux problèmes de précision lors de l’arrondi, entre autres considérations telles que la portabilité, etc. Consultez le blog d’Aaron Bertrand .


Microsoft et les concepteurs de langage ont choisi l’arrondissement des banquiers parce que les concepteurs de matériel l’ont choisi [citation?]. Il est inscrit dans les normes de l’Institut des ingénieurs élecsortingciens et électroniciens (IEEE), par exemple. Et les concepteurs de matériel l’ont choisi parce que les mathématiciens le préfèrent. Voir Wikipedia ; pour paraphraser: l’édition de 1906 de Probability and Theory of Errors a appelé cette “règle de l’ordinateur” (“ordinateurs” signifiant les humains qui effectuent des calculs).

Nous avons récemment mis en place un système qui doit gérer les valeurs dans plusieurs devises et les convertir entre elles, et a trouvé certaines choses difficiles.

NE JAMAIS UTILISER DE NUMÉROS DE POINT FLOTTANT POUR L’ARGENT

L’arithmétique en virgule flottante introduit des inexactitudes qui peuvent ne pas être remarquées tant qu’elles n’ont pas été vissées. Toutes les valeurs doivent être stockées sous forme d’entiers ou de types à décimales fixes. Si vous choisissez d’utiliser un type à décimales fixes, assurez-vous de comprendre exactement ce que ce type fait sous le capot (utilise-t-il en interne un nombre entier ou flottant)? type).

Lorsque vous devez effectuer des calculs ou des conversions:

  1. Convertir les valeurs en virgule flottante
  2. Calculer une nouvelle valeur
  3. Arrondir le nombre et le reconvertir en entier

Lors de la conversion d’un nombre à virgule flottante en entier à l’étape 3, ne vous contentez pas de le lancer – utilisez une fonction mathématique pour arrondir le premier. Ce sera généralement round , bien que dans certains cas, il puisse s’agir de floor ou de ceil . Connaître la différence et choisir avec soin.

Stocker le type d’un numéro à côté de la valeur

Cela peut ne pas être aussi important pour vous si vous ne traitez qu’une seule devise, mais il était important pour nous de gérer plusieurs devises. Nous avons utilisé le code à 3 caractères pour une devise, par exemple USD, GBP, JPY, EUR, etc.

Selon la situation, il peut également être utile de stocker:

  • Si le nombre est avant ou après impôt (et quel était le taux de taxe)
  • Si le nombre est le résultat d’une conversion (et de quoi il a été converti)

Connaître les limites de précision des nombres que vous traitez

Pour les valeurs réelles, vous voulez être aussi précis que la plus petite unité de la devise. Cela signifie que vous n’avez aucune valeur inférieure à un centime, un centime, un yen, un fen, etc. Ne stockez pas les valeurs avec plus de précision que cela, sans aucune raison.

En interne, vous pouvez choisir de gérer des valeurs plus petites, auquel cas il s’agit d’un type de valeur de devise différent . Assurez-vous que votre code sait qui est qui et ne les mélange pas. Évitez d’utiliser des valeurs à virgule flottante même ici.


En ajoutant toutes ces règles ensemble, nous avons décidé des règles suivantes. Dans le code en cours d’exécution, les devises sont stockées à l’aide d’un entier pour la plus petite unité.

 class Currency { Ssortingng code; // eg "USD" int value; // eg 2500 boolean converted; } class Price { Currency grossValue; Currency netValue; Tax taxRate; } 

Dans la firebase database, les valeurs sont stockées sous la forme d’une chaîne au format suivant:

 USD:2500 

Cela stocke la valeur de 25,00 $. Nous avons pu le faire uniquement parce que le code traitant des devises n’a pas besoin d’être dans la couche même de la firebase database, de sorte que toutes les valeurs peuvent être converties en mémoire en premier. D’autres situations se prêtent sans doute à d’autres solutions.


Et au cas où je ne l’aurais pas dit plus tôt, n’utilisez pas float!

Lorsque vous manipulez de l’argent en MySQL, utilisez DECIMAL (13,2) si vous connaissez la précision de vos valeurs monétaires ou si vous utilisez DOUBLE si vous voulez juste une valeur approximative assez bonne et rapide. Donc, si votre application doit gérer des valeurs monétaires pouvant atteindre un billion de dollars (ou des euros ou des livres), cela devrait fonctionner:

 DECIMAL(13, 2) 

Ou, si vous devez vous conformer aux PCGR, utilisez:

 DECIMAL(13, 4) 

4 décimales vous donneraient la précision nécessaire pour stocker les plus petites sous-unités monétaires du monde. Vous pouvez aller plus loin si vous avez besoin d’une précision de micropaiement (nanopaiement ?!).

Je préfère aussi DECIMAL aux types de fonds spécifiques aux SGBD, vous êtes plus en sécurité en maintenant ce type de logique dans l’application IMO. Une autre approche dans le même sens consiste simplement à utiliser un entier [long], avec une mise en forme dans ¤unit.subunit pour la lisibilité humaine (¤ = symbole monétaire) effectuée au niveau de l’application.

Le type de données money sur SQL Server comporte quatre chiffres après la décimale.

À partir de la documentation en ligne de SQL Server 2000:

Les données monétaires représentent des montants d’argent positifs ou négatifs. Dans Microsoft® SQL Server ™ 2000, les données monétaires sont stockées à l’aide des types de données money et smallmoney. Les données monétaires peuvent être stockées avec une précision de quatre décimales. Utilisez le type de données monétaire pour stocker des valeurs comsockets entre -922 337 203 685 477,5808 et +922 337 203 685 477,5807 (nécessite 8 octets pour stocker une valeur). Utilisez le type de données smallmoney pour stocker des valeurs comsockets entre -214748.3648 et 214.748.3647 (nécessite 4 octets pour stocker une valeur). Si un nombre supérieur de décimales est requirejs, utilisez plutôt le type de données décimal.

Parfois, vous devrez aller à moins d’un cent et il y a des devises internationales qui utilisent de très grandes démoniations. Par exemple, vous pouvez facturer à vos clients 0,088 cent par transaction. Dans ma firebase database Oracle, les colonnes sont définies comme NUMBER (20,4)

Si vous envisagez d’effectuer des opérations arithmétiques dans la firebase database (en multipliant les taux de facturation, etc.), vous voudrez probablement obtenir beaucoup plus de précision que ce que les gens suggèrent, pour les mêmes raisons que vous ne le feriez jamais. voulez utiliser quelque chose de moins qu’une valeur à virgule flottante double précision dans le code de l’application.

Si vous utilisiez IBM Informix Dynamic Server, vous auriez un type MONEY, variante mineure du type DECIMAL ou NUMERIC. C’est toujours un type à virgule fixe (alors que DECIMAL peut être un type à virgule flottante). Vous pouvez spécifier une échelle de 1 à 32 et une précision de 0 à 32 (par défaut à une échelle de 16 et une précision de 2). Ainsi, en fonction de ce que vous devez stocker, vous pouvez utiliser DECIMAL (16,2) – encore assez gros pour contenir le déficit fédéral américain – ou vous pouvez utiliser une plage plus petite ou plus de décimales.

Une réponse tardive ici, mais j’ai utilisé

 DECIMAL(13,2) 

ce que j’ai raison de penser devrait permettre jusqu’à 99 999 999 999,99.

Je pense que pour une large part, vos exigences ou celles de votre client devraient déterminer la précision et l’échelle à utiliser. Par exemple, pour le site de commerce électronique sur lequel je travaille et qui traite uniquement de l’argent en GBP, il m’a été demandé de le conserver à la décimale (6, 2).