IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

VB.NET Discussion :

Quel type de variables pour faire des calculs financiers ?


Sujet :

VB.NET

  1. #1
    Membre averti
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2012
    Messages
    640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Mars 2012
    Messages : 640
    Points : 372
    Points
    372
    Par défaut Quel type de variables pour faire des calculs financiers ?
    Bonjour à tous,
    J'ai cherché partout l'information j'ai un peu de mal à savoir quel type de variables je dois utiliser pour faire des calculs financiers.
    Autant cela me parait évident pour les valeurs en Euros, ça l'ai beaucoup moins pour les valeurs fractionnaires.
    Cela concernent les variables dans mon programme mais aussi les types de champs dans ma base Access.

    Exemple pour le calcul de la marge en % = Marge en Euros/PV) :
    ------------------------------------------------------------------
    Désignation | Valeur | Variable VB.NET | Variable Access
    ------------------------------------------------------------------
    Prix de Revient | 900.00 € | Décimal | DataTypeEnum.adCurrency
    Prix de Vente | 950.00 € | Décimal | DataTypeEnum.adCurrency
    Marge | 50.00 € | Décimal | DataTypeEnum.adCurrency
    Marge en % | 0.0526... | ??????? | ????????
    ------------------------------------------------------------------

    je ne sais pas si l'exemple est bien choisi mais le but est d'éviter les erreurs d'arrondies.
    Merci beaucoup si vous pouvez me conseiller.

  2. #2
    Membre confirmé

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2011
    Messages
    244
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 46
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2011
    Messages : 244
    Points : 574
    Points
    574
    Par défaut
    Hello,
    Le mieux c'est de ne pas stocker la marge étant donné qu'elle se calcule depuis le prix d'achat et le prix de vente. Comme cela tu n'auras pas de problème d'arrondis.
    "C'est tellement merdique que toute modification est une amélioration !"

  3. #3
    Membre averti
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2012
    Messages
    640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Mars 2012
    Messages : 640
    Points : 372
    Points
    372
    Par défaut
    Bonjour et merci de me répondre.
    C'est une idée en effet. Je vais malgré tout stocker la marge, juste pour pouvoir l'afficher mais j'éviterais de réutiliser cette valeur dans mes calculs comme ça je n'ai plus de problème.
    Presque au hasard je dirais , je vais utiliser les singles dans le code et l'équivalent en Access : (type DataTypeEnum.adSingle).

    Je marque résolu, mais si quelqu'un a une autre suggestion qu'il n'hésite pas.

  4. #4
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 485
    Points
    5 485
    Par défaut
    En principe les calculs financiers se font avec "decimal" (19 28 chiffres significatifs). Mais ça c'est pour de vrais calculs financiers. S'il ne s'agit que d'afficher un résultat à l'utilisateur ou de faire un peu de compatibilité, single (7 chiffres significatifs) ou double (15 chiffres significatifs) suffisent amplement. Avec 7 chiffres significatifs tu fais sans problème tes additions au centime d'euro près pour des sommes inférieures à 100k€.

    Enfin attention à ne pas confondre les problèmes de représentation avec des problèmes d'arrondis. Par exemple 1/10 ne peut pas être représenté en binaire avec un nombre fini de bits significatifs (tout comme 1/3 ne peut pas l'être en décimal - ils sont irrationnels). Ceci n'est pas une erreur d'arrondi qui se résoudrait en augmentant la précision mais quelque chose qui se traite par un formatage adéquat de l'affichage, ou en optant pour le type decimal qui est exprimé en base 10.


    EDIT: correction. Les 19 chiffres significatifs précédemment mentionnés correspondent en fait aux nombres sur 80 bits qui n'ont pas de mot clé associé sous dotnet.

  5. #5
    Membre averti
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2012
    Messages
    640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Mars 2012
    Messages : 640
    Points : 372
    Points
    372
    Par défaut
    Bonjour et merci de me répondre.
    J'ai décoché résolu parce que ce qui me parraissait evident l'est de moins en moins . (Je ferais des essais sur mon PC de devellopement dès ce soir mais pour le moment je suis dans le flou complet concernant le type decimal et Currency (Access))
    Je dit peut-être une bétise et mais il me semble que le type Decimal (et Currency) arrondi à 2 chiffres aprés la virgule et je peux me retrouver avec le cas suivant :

    Si j'ai un prix de câble égale à 15€ le kilométre et que je stocke le prix au métre dans une variable décimale ou dans un champ Currency (Access), je risque d'arrondir le prix au métre à 0.01€ et donc avec une précision insuffisante dans ce cas. le prix réel etant de 0.015€.

    Dans ce cas faut'il définir au cas par cas les types de variable selon la maniere dont ils interviennent dans le calcul ? Je me demande aussi si la variable Decimal correspond bien au type Currency.
    Je commence à être un peu perdu.

  6. #6
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 485
    Points
    5 485
    Par défaut
    Avant toute chose je tiens à préciser que je n'ai aucune compétence concernant Access, mon unique expérience avec ce dernier se résumant à une après-midi d'initiation il y a plus de quinze ans.

    Cela étant dit, sur dotnet le type decimal est un type en virgule flottante et il n'y a donc aucune histoire d'arrondi automatique à deux chiffres après la virgule. Sa principale spécificité est le fait qu'il est exprimé sous la forme a*10^b au lieu du a*2^b des autres types réels, ce qui évite les problèmes de représentativité dans certaines applications. Qui plus est il a une grande précision (128 bits contre 64 pour double et 32 pour single) et l'essentiel de ces 128 bits sont utilisés pour la mantisse, au détriment de l'exposant, si bien que l'intervalle couvert va environ de ±1E28 à ±1E-28.

    Maintenant, concernant Access, Google m'a renvoyé cette page. Single et Double correspondent à leurs équivalents C# mais Currency est un type spécifique à Access avec un fonctionnement différent des autres types puisqu'il est en virgule fixe. Très vraisemblablement c'est un entier en 64 bits représentant des dix-millièmes d'unité, ce qui évite les problèmes de représentativité (sur la page que j'ai donnée il est défini comme contenant 15 chiffres avant la virgule, et 4 après, or 2^64 = 1.8E19).

    Du coup, si les problèmes de représentativité sont importants (et ils le sont sans doute), opte simplement pour decimal côté c# et currency côté Access. Sinon choisis de chaque côté en fonction du nombre de chiffres significatifs dont tu as besoin, quitte à doubler la précision du côté (C# ou Access) où tu as des calculs élaborés à faire, ou si tu ne sais pas s'ils sont élaborés (méthode grossière mais qui évite d'avoir à se plonger dans les arcanes du calcul numérique).


    EDIT : Grosse édition importante, liée au fait que decimal et currency évitent les problèmes de représentativité, et au fait que j'ai pigé ce qu'est vraiment currency.

  7. #7
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 485
    Points
    5 485
    Par défaut
    Au cas où tu aurais lu le précédent message avant édition et que tu ne repasses pas sauf notification par e-mail d'un nouveau message, en voici un pour signaler d'importants changements dans le message précédent.

  8. #8
    Membre averti
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2012
    Messages
    640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Mars 2012
    Messages : 640
    Points : 372
    Points
    372
    Par défaut
    Merci DonQuiche pour ces explications, ca me semble déja plus claire.
    Je ferais des essais ce soir pour me rendre compte vraiment comment se comporte ces types Decimal et Currency.

  9. #9
    Membre averti
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2012
    Messages
    640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Mars 2012
    Messages : 640
    Points : 372
    Points
    372
    Par défaut
    Bonsoir, j'ai un autre problème liée aux types Décimal et Currency :
    Depuis que j'ai introduit ces type de variables, mon programme détecte systématiquement des écarts entre les valeurs originales contenues dans la base (DataSet) et les valeurs calculées dans mon programme.
    Un exemple pour être plus précis :
    - Je calcul une valeur que je stocke dans une variable type décimal (Valeur = 335,913981) (Nombre de chiffres après la virgule dépend du calcul et de la précision inhérente au type Décimal)
    - je stocke cette valeur dans un champ Currency de ma base (Valeur stockée = 335,914) (Access arrondie normalement à 4 chiffres après la virgule, 3 dans ce cas)

    Mon programme étant conçue pour comparer la valeur courante avec la valeur originale, il me propose d'enregistrer les modifications étant donné qu'il considère que les 2 valeurs sont différentes ce qui est un comportement normale du programme. Mais je ne sais plus comment faire pour éviter ca. Est-ce que je doit arrondir les variables décimal à 4 chiffres après la virgules? , ça me parait bizarre de devoir faire cela et comment ? Je m'arrache les cheveux sur ce problème que je croyais pourtant simple.

  10. #10
    Membre confirmé

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2011
    Messages
    244
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 46
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2011
    Messages : 244
    Points : 574
    Points
    574
    Par défaut
    Hello,
    Pour pouvoir t'aider, j'ai besoin de comprendre pourquoi tu as des chiffres à arrondir. Quelles sont les opérations que tu effectues et quelle est leur signification ? (Par exemple tu pourrais stocker dans ta base le montant unitaire et le nombre d'unités pour des produits de type : 3 pour 10€, ce qui t'oblige à effectuer un arrondi.)
    "C'est tellement merdique que toute modification est une amélioration !"

  11. #11
    Membre averti
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2012
    Messages
    640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Mars 2012
    Messages : 640
    Points : 372
    Points
    372
    Par défaut
    Bonjour plume13,
    Il n'y a rien qui m'oblige, simplement j'ai le soucis de vouloir faire les choses correctement, notament au niveau de la définition des type de champs dans la base qu'il est trés difficile de modifier une fois que l'application est déployée.
    J'ai lu quelque part que le type Decimal était adapté pour faire des calculs financiers et je me dit qu'il en est de même pour le type Currency (Access) mais il semblerait que ce dernier ne soit pas l'équivalent de Decimal.
    Si c'est trop compliqué j'utiliserais des types double partout mais je suis quand même étonné du comportement que j'ai cité plus haut, il y un truc qui m'echappe.
    Mes calculs doivent être au niveau de ce que fait un logiciel de devis par exemple (calculs de marge Net, Marge Brut, Prix de revient, Prix de vente, Prix unitaire...etc)

  12. #12
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 485
    Points
    5 485
    Par défaut
    J'ai dans l'idée qu'il y a peut-être un problème dans la façon dont tes données sont envoyées à Access. As-tu essayé une insertion manuelle, en créant toi-même une requête SQL de mise à jour, avec une chaîne concaténée par tes soins?

  13. #13
    Membre confirmé

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2011
    Messages
    244
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 46
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2011
    Messages : 244
    Points : 574
    Points
    574
    Par défaut
    Je te demande plus de détail pour pouvoir t'aider intelligemment.

    Le fonctionnement que tu décris n'est pas du tout illogique : currency est sensé traiter des devises, soit au maximum 4 décimales après la virgule. Si tu fais des calculs sur tes montants, tu peux obtenir plus de 4 décimales, d'où la nécessité d'arrondi...
    Le tout étant de savoir si il vaut mieux arrondir avant (en C#) ou après (via Access), sachant qu'au final le prix payé par la personne sera toujours avec 2 décimales après la virgule (en €).

    Utiliser un type double ne résoudra pas ton problème, car les arrondis existeront toujours (et en plus les calculs pourront être faux à cause justement des arrondis sur les doubles qui sont des nombres à virgule flottante, je sais de quoi je parle car j'ai travaillé sur de la compta et je me suis arraché les cheveux !).

    Donc si tu me donnes plus de précision, je pourrai peut-être t'aiguiller...
    "C'est tellement merdique que toute modification est une amélioration !"

  14. #14
    Membre averti
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2012
    Messages
    640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Mars 2012
    Messages : 640
    Points : 372
    Points
    372
    Par défaut
    Bonjour DonQuiche, Je n'ai pas essayé ca, je ne pourrais le faire que ce soir.
    Actuellement mes données sont insérés dans la base à partir de contôles liés (DataBinding). Pour la lecture des valeurs je passe par une procédure qui contrôle la validité et convertie mon Text en Decimal, pour l'écriture je convertie dans l'autre sens (je ne pense pas que le problème vienne de là mais je pourrais toujours regarder de plus prés).

  15. #15
    Expert confirmé Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Points : 5 485
    Points
    5 485
    Par défaut
    Citation Envoyé par BasicZX81 Voir le message
    Actuellement mes données sont insérés dans la base à partir de contôles liés (DataBinding). Pour la lecture des valeurs je passe par une procédure qui contrôle la validité et convertie mon Text en Decimal, pour l'écriture je convertie dans l'autre sens (je ne pense pas que le problème vienne de là mais je pourrais toujours regarder de plus prés).
    Ce que je suspecte c'est que le driver ODBC derrière ADO.net communique en binaire plutôt qu'en mode texte, avec une conversion de ta valeur en base décimale vers une base binaire s'il n'y a pas de support pour les valeurs numériques en base décimale. Une communication en mode texte, via une classique requête SQL, éviterait ça.

  16. #16
    Membre averti
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2012
    Messages
    640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Mars 2012
    Messages : 640
    Points : 372
    Points
    372
    Par défaut
    Bonjour DonQuiche,
    J'ai trouvé ça mais je ne sais pas si il y a un rapport avec le problème :
    http://visualbasic.about.com/od/usin...ecdatatype.htm

    Plume13, effectivement je fait des calculs sur les montants et si je stocke le résultat dans une variable Decimal j'obtiens plus de 4 chiffres aprés la virgule. Je me rends compte que mon ignorance dans ce domaine est énorme, je ne sais pas si il faut arrondir ou pas et comment. Entre le type decimal qui est en virgule flottante qui peut contenir plus de 4 chiffres aprés la virgule et le type Currency en virgule fixe qui tronque à 4 chiffres après la virgule je suis complétement pommé. Pourtant ces 2 types semblent finalement trés différents et pourtant ils sont décrits comme etant adaptés aux calculs ficanciers.

  17. #17
    Membre confirmé

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2011
    Messages
    244
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 46
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2011
    Messages : 244
    Points : 574
    Points
    574
    Par défaut
    Le type currency peut être utilisé si tu stockes des montants. Si c'est des calculs sur des montants avec des divisions à tire-larigot, c'est plus trop des montants car tu as besoin dans ce cas de plus de 4 décimales après la virgule pour pouvoir des opérations inverses.

    C'est pour ça que je te demandes quels types de calculs tu effectues, car tu as peut-être une autre manière de représenter ces montants.

    PS : n'essaie pas d'utiliser des requêtes construites à la main, dans ton cas, cela ne changera rien.
    "C'est tellement merdique que toute modification est une amélioration !"

  18. #18
    Membre averti
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2012
    Messages
    640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Mars 2012
    Messages : 640
    Points : 372
    Points
    372
    Par défaut
    Bonjour Plume13 et merci de m'aider,
    Voici un exemple de calcul que je suis ammenné à faire :
    FG: Montant des Frais généraux en €
    %FG : Frais generaux en pourcentage
    MD : Montant du Devis en €
    FO : Montant des fournitures en €
    MO : Montant de la main d'oeuvre en €
    ET : Montant des Etudes en €
    FD : Montant des Frais Divers en €
    MP : Marge previsionelle en €

    FG=MD*%FG
    MP=MD-FO-MO-ET-FD-FG

    C'est un exemple parmis d'autres mais j'ai des écarts sur ces 2 résultats (entre les valeurs stockées dans la base (Currency) et les valeurs calculées dans le programme (Decimal).

  19. #19
    Membre confirmé

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2011
    Messages
    244
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 46
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2011
    Messages : 244
    Points : 574
    Points
    574
    Par défaut
    OK, alors vu ce que tu fais comme calcul, je te conseille d'arrondir les montants que tu veux sauvegarder avant des les enregistrer (en arrondi bancaire quant à faire) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    MP = Math.Round(MD-FO-MO-ET-FD-FG, MidpointRounding.ToEven)
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    FG = Math.Round(MD*%FG, MidpointRounding.ToEven);
    MP = MD-FO-MO-ET-FD-FG;
    En partant du principe que dans le premier cas, tu n'enregistres en base que MP, et dans le second que tu enregistres FG et MP.
    Comme je le disais dans un post plus haut, au final, le client paie les montants arrondis, il faut donc arrondir le plus tard possible
    "C'est tellement merdique que toute modification est une amélioration !"

  20. #20
    Membre averti
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2012
    Messages
    640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Mars 2012
    Messages : 640
    Points : 372
    Points
    372
    Par défaut
    Merci Plume13, je comprends le principe. Je ne pensais pas que ca me menerait à faire des arrondies et je suppose aussi qu'il faut faire attention de ne pas utiliser des valeurs arrondies et non arrondies dans un même calcul.
    Je vais tester tout ça, en te remerciant.

Discussions similaires

  1. [AC-2007] quel type de variable pour récupérer des objets de type Ole
    Par rominous41 dans le forum VBA Access
    Réponses: 2
    Dernier message: 25/05/2011, 16h59
  2. [TPW] Jeux de rôle : quels types de variables pour coder des personnages ?
    Par maxiNoob dans le forum Turbo Pascal
    Réponses: 81
    Dernier message: 07/12/2009, 11h54
  3. Réponses: 2
    Dernier message: 05/02/2008, 11h47
  4. [SQL] Récupération éventuelle d'une variable pour faire des tests
    Par mougeole dans le forum PHP & Base de données
    Réponses: 4
    Dernier message: 24/05/2006, 13h56
  5. utiliser données texte pour faire des calculs
    Par sarah67 dans le forum Access
    Réponses: 20
    Dernier message: 06/02/2006, 14h09

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo