189 votes

Ranger l’argent dans une colonne decimal - quelle précision et échelle ?

Je suis à l'aide d'une colonne decimal pour stocker les valeurs de la monnaie sur une base de données, et aujourd'hui, je me demandais ce que la précision et l'échelle à utiliser.

Depuis la soi-disant char colonnes de largeur fixe sont plus efficaces, je pensais la même chose pourrait être vraie pour les colonnes decimal. S'agit-il?

Et quelle précision et l'échelle dois-je utiliser? Je pensais précision 24/8. C'est que overkill, ou pas assez ok?


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

  • Stocker le taux de conversion (le cas échéant) dans la table des transactions en lui-même, comme un float
  • Magasin de la monnaie dans la table compte
  • Le montant de la transaction sera un DECIMAL(19,4)
  • Tous les calculs à l'aide d'un taux de conversion seront traitées par mon application j'ai donc garder le contrôle de l'arrondi

Je ne pense pas qu'un flotteur pour le taux de conversion est un problème, puisque c'est surtout pour la référence, et je vais être un moulage d'une virgule, de toute façon.

Merci à vous tous pour votre précieuse contribution.

209voto

onedaywhen Points 24594

Si vous cherchez un one-size-fits-all, je vous suggère DECIMAL(19, 4) est un choix populaire (un rapide Google en témoigne). Je pense que cela provient de l'ancien VBA/Access/Jet type de données monétaire, étant le premier point fixe de type décimal dans la langue; Decimal seulement sont entrés dans la version 1.0' style (c'est à dire pas entièrement mis en œuvre) en VB6/VBA6/Jet 4.0.

La règle de base pour le stockage de point fixe des valeurs décimales est pour stocker au moins une décimale après la virgule que vous avez réellement besoin pour permettre l'arrondissement. L'une des raisons pour la cartographie de la vieux - Currency type à l'extrémité avant d' DECIMAL(19, 4) type dans le back-end est qu' Currency présentaient des banquiers arrondi par nature, tandis qu' DECIMAL(p, s) arrondi par troncature.

Un supplément de décimale dans le stockage pour l' DECIMAL permet une coutume algorithme arrondi à être mis en œuvre plutôt que de prendre le fournisseur par défaut (et des banquiers arrondissement est alarmant, pour dire le moins, pour un concepteur attend à ce que tous les valeurs se terminant par, 5 à la ronde à l'écart à partir de zéro).

Oui, DECIMAL(24, 8) sons comme exagéré pour moi. La plupart des devises sont cotées à quatre ou cinq décimales. Je sais de situations où une échelle décimale de 8 (ou plus) est nécessaire, mais c'est là un "normal" montant monétaire (par exemple quatre décimales) a été pro rata d, ce qui implique la précision décimale doit être réduite en conséquence (également tenir compte d'un type à virgule flottante dans de telles circonstances). Et on n'a pas beaucoup d'argent aujourd'hui pour exiger une précision décimale de 24 :)

Cependant, plutôt que de one-size-fits-all approche, certaines recherches peuvent être dans l'ordre. Demandez à votre concepteur ou de l'expert du domaine sur les règles comptables qui peuvent être applicables: les PCGR, UE, etc. J'ai vaguement rappeler certains pays de l'UE intra-des transferts de l'état avec des règles explicites pour l'arrondi à cinq décimales, donc à l'aide de DECIMAL(p, 6) pour le stockage. Comptables généralement semblent favorables à quatre décimales.


PS Éviter de SQL Server MONEY type de données, car il a de sérieux problèmes avec la précision lors de l'arrondissement, parmi d'autres considérations, telles que la portabilité etc. Voir Aaron Bertrand blog.


Microsoft et la langue concepteurs ont choisi l'arrondi parce que les concepteurs de matériel choisi [citation?]. Il est consacré par l'Institute of Electrical and Electronics Engineers (IEEE), par exemple les normes. Et les concepteurs de matériel choisi parce que les mathématiciens préfèrent. Voir Wikipédia; pour paraphraser: 1906 édition des Probabilités et Théorie des Erreurs appelé ce "le de l'ordinateur règle" ("ordinateurs" en ce sens, les humains qui effectuer des calculs).

114voto

Marcus Downing Points 5250

Nous avons récemment mis en place un système qui doit gérer des valeurs dans de multiples devises et convertir entre eux, et a trouvé quelques choses à la dure.

NE JAMAIS UTILISER DES NOMBRES À VIRGULE FLOTTANTE DE L'ARGENT

Arithmétique à virgule flottante introduit des inexactitudes qui peuvent ne pas être remarqué jusqu'à ce qu'ils ont vissé quelque chose. Toutes les valeurs doivent être stockés comme des entiers ou des décimaux types, et si vous choisissez d'utiliser un corrigé-type décimal puis assurez-vous que vous comprenez exactement ce que ce type n'sous le capot (c'est à dire, ne l'interne, l'utilisation d'un nombre entier ou à virgule flottante).

Lorsque vous avez besoin de faire des calculs ou des conversions:

  1. Convertir des valeurs à virgule flottante
  2. Calculer la nouvelle valeur
  3. Arrondir le nombre et la reconvertir en un entier

Lors de la conversion d'un nombre à virgule flottante à un nombre entier dans l'étape 3, ne pas les jeter elle - utiliser une fonction mathématique pour le tour en premier. Ce sera habituellement round, bien que dans des cas particuliers, il pourrait être floor ou ceil. Connaître la différence et choisir avec soin.

Stocker le type d'un nombre à côté de la valeur

Cela peut ne pas être aussi important pour vous si vous êtes seulement de la manipulation de monnaie, mais il était important pour nous dans le traitement des devises multiples. Nous avons utilisé les 3 caractères de code pour une devise, comme l'USD, GBP, JPY, EUR, etc.

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

  • Si le nombre est avant ou après impôt (et que le taux de taxe a)
  • Si le nombre est le résultat d'une conversion (et ce qu'il a été converti à partir d')

Connaître la précision des limites des nombres que vous avez à traiter avec des

Pour des valeurs réelles, vous voulez être précis comme la plus petite unité de la devise. Cela signifie que vous n'avez pas de valeurs plus petites que un centime, un centime, un yen, d'un marais, etc. Ne pas stocker des valeurs avec une précision plus élevée que celle pour aucune raison.

En interne, vous pouvez choisir de traiter avec des petites valeurs, auquel cas c'est un autre type de valeur de la monnaie. Assurez-vous que votre code ne sait qui est qui et ne pas les mélanger. Évitez d'utiliser des valeurs à virgule flottante, même ici.


L'ajout de toutes ces règles ensemble, nous avons décidé sur les règles suivantes. Dans le code en cours d'exécution, les monnaies sont stockées à l'aide d'un entier dans la plus petite unité.

class Currency {
   String code;       //  eg "USD"
   int value;         //  eg 2500
   boolean converted;
}

class Price {
   Currency grossValue;
   Currency netValue;
   Tax taxRate;
}

Dans la base de données, les valeurs sont stockées en tant que chaîne de caractères dans le format suivant:

USD:2500

Qui stocke la valeur de $25.00. Nous avons été en mesure de le faire seulement parce que le code qui traite des monnaies n'a pas besoin d'être à l'intérieur de la couche de base de données elle-même, de sorte que toutes les valeurs peuvent être converties en mémoire. D'autres situations sera sans aucun doute se prêtent à d'autres solutions.


Et dans le cas où je n'ai pas précisé plus haut, ne pas utiliser de flotter!

2voto

bobince Points 270740

4DP vous donnerait l’exactitude pour stocker plus petites sous-unités monnaie du monde. Vous pouvez le prendre vers le bas supplémentaire si vous avez besoin de précision de micropaiement (nanopayment ? !).

Je préfère trop Decimales types de fonds propres au SGBD, vous êtes plus sûr de garder ce genre de logique dans l’application de l’OMI. Une autre approche dans le même sens est tout simplement d’utiliser un entier [long], avec mise en forme dans ¤unit.subunit pour plus de lisibilité humaine fait au niveau de l’application.

1voto

Austin Salonen Points 28057

L'argent de type de données sur SQL Server dispose de quatre chiffres après la virgule.

À partir de SQL Server 2000 Livres en Ligne:

Les données monétaires représente des montants positifs ou négatifs de l'argent. Dans Microsoft® SQL Server™ 2000, monétaire, les données sont stockées à l'aide de l'argent et smallmoney types de données. Monétaire, les données peuvent être stockées pour une précision de quatre décimales. L'utilisation de l'argent de type de données pour stocker des valeurs dans la plage de -922,337,203,685,477.5808 à +922,337,203,685,477.5807 (nécessite 8 octets pour stocker une valeur). Utiliser le smallmoney type de données à stocker des valeurs dans la plage de -214,748.3648 par 214,748.3647 (nécessite 4 octets pour stocker une valeur). Si un plus grand nombre de décimales sont nécessaires, utilisez le type de données décimal au lieu.

1voto

WW. Points 11335

Parfois vous aurez besoin d’aller à moins d’un centime et il y a des monnaies internationales qui utilisent demoniations très grandes. Par exemple, vous pourriez charger vos clients 0,088 cents par transaction. Dans ma base de données Oracle, les colonnes sont définies comme NUMBER(20,4)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X