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

WinDev Discussion :

Format réel, des décimales qui n'ont pas lieu d'être [WD17]


Sujet :

WinDev

  1. #21
    Membre expérimenté
    Inscrit en
    Août 2010
    Messages
    726
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 726
    Points : 1 645
    Points
    1 645
    Par défaut
    Ah oui, je comprends mieux.
    Effectivement, il faut tout faire en décimal. (types "numérique" et "monétaire")
    Pour ma part, je l'ai toujours fait donc je ne me rends même plus compte du bénéfice.
    Surtout que, même si WD peut arrondir les angles sur les comparaisons (et encore, on ne sait pas vraiment ce qu'il fait), ça ne sera pas le cas de SQL Server dans une requête. Donc le FLOAT est à bannir. (et le réel de WD par la même occasion)

  2. #22
    Membre averti Avatar de droliprane
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Mai 2005
    Messages
    710
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Vendée (Pays de la Loire)

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2005
    Messages : 710
    Points : 444
    Points
    444
    Par défaut
    Ok donc dans ma base vous me conseillez de basculer tous mes float en decimal ?

    Ca fait que selon le champs je dois faire gaffe à bien lui donner le nombre de décimales que je veux "decimal(18, n)"

    Le float était bien pratique pour ça, c'est que je n'avais pas à me soucier de typer plus fortement le champs...

    je ne sais pas quoi faire
    'Diviser chacune des difficultés en autant de parcelles qu’il se pourrait et qu’il serait requis pour les mieux résoudre', René Descartes

    => Maya GPAO

  3. #23
    Membre expérimenté
    Inscrit en
    Août 2010
    Messages
    726
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 726
    Points : 1 645
    Points
    1 645
    Par défaut
    Prenez le monétaire de WinDev pour référence, si vous voulez. Il a beaucoup servi dans plein de projets et semble convenir dans une énorme majorité de cas.
    L'équivalent en SQL Server est : DECIMAL(23,6)

    Mais tout dépend de l'usage que vous en faites, et pouvoir adapter le type à vos besoins (de précision, ou de marge de manoeuvre) devrait au contraire vous rassurer.

    En fait, pour optimiser un peu, on peut utiliser (19,6), qui me paraît suffisant dans le cas général.

  4. #24
    Membre émérite
    Avatar de DelphiManiac
    Homme Profil pro
    Homme à tout faire
    Inscrit en
    Mars 2002
    Messages
    1 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Homme à tout faire
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 147
    Points : 2 533
    Points
    2 533
    Par défaut
    Citation Envoyé par bvadam Voir le message
    Ok donc dans ma base vous me conseillez de basculer tous mes float en decimal ?

    Ca fait que selon le champs je dois faire gaffe à bien lui donner le nombre de décimales que je veux "decimal(18, n)"

    Le float était bien pratique pour ça, c'est que je n'avais pas à me soucier de typer plus fortement le champs...

    je ne sais pas quoi faire
    Ta dernière question est quelque peu déroutante . 2 pages pour t'expliquer que l'on ne peut faire une confiance absolu au réel quand il s'agit de calcul qui demande un maximum de précision et tu demandes si tu dois changer !!

    2 solutions :
    - Soit tu passes par des "décimals", c'est le choix qui me paraît le plus naturel vu que ce sont des types de données prévues pour cela.
    - Soit tu restes avec des rééls et tu te dois de gérer les erreurs d'arrondi potentielles.
    Si ce message vous a semblé utile, il est possible qu'il soit utile à d'autres personnes. Pensez au . Et n'oubliez pas le le moment venu !

    On n'a pas à choisir si l'on est pour ou contre la décroissance, elle est inéluctable, elle arrivera qu'on le veuille ou non.

  5. #25
    Membre éclairé
    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    303
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 303
    Points : 812
    Points
    812
    Par défaut
    Bonjour à tous,

    Après avoir vérifié sur Windows XP, le type de données "réel" de Windev est basé sur la norme IEEE-754 (représentation binaire d'un nombre à virgule flottante).

    De mon point de vue, utiliser le mot "réel" pour nommer ce type de données peut induire en erreur: je comprends mieux "flottant".

    Sur le web on peut trouver énormément de ressources sur le sujet des nombres à virgule flottante, des approximations inhérentes à cette représentation et sur la manière de prendre en compte ces approximations lors de tests de comparaison (cf. epsilon).

    Pour en revenir à la question du comportement de l'opérateur = appliqué aux nombres réels, comme relevé par DelphiManiac.

    Citation Envoyé par DelphiManiac Voir le message
    J'avoue ne pas avoir lancer mon test sous Windev, ce que je viens de faire, et le résultat est encore plus imprévu ^^ La valeur n'est pas égale à 0, mais le test d'égalité à 0 renvoie vrai, affolant par contre là :p

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    f est un réel
    f = (5-4.9)-0.1
    Trace(f)
     
    SI f=0 ALORS
    	Trace("f=0")
    SINON
    	Trace("f<>0")
    FIN
    Résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    -0.0000000000000003608224830032
    f=0
    Ce code là est pour le moins perturbant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SI 0.0000001 = 0.00 ALORS
    	Trace("égal")
    SINON
    	Trace("différent")
    FIN
    Devinez le résultat

    Comportement pour le moins aberrant. Moralité, il faut vraiment prendre le maximum de précautions quand on manipule des réels.
    Le fonctionnement de l'opérateur = est expliqué ici "Opérateurs de comparaison".

    Voici le paragraphe qui nous intéresse où l'opérateur = est expliqué, ainsi qu'un exemple d'alternative pour coder un test "adapté" à une situation particulière (utiliser un écart relatif):
    Citation Envoyé par Aide en ligne: Opérateurs de comparaison
    Egalité et comparaison : Réel contenant plus de 6 décimales de différence

    Le test d'égalité de deux réels est effectué en ne tenant compte que des 6 premières décimales. En effet, les erreurs d'arrondi dues au codage interne des réels nécessitent un test spécifique.

    Ce test doit être réalisé en comparant la différence des deux valeurs à tester avec une valeur de référence. Selon le type de votre application, cette valeur peut être égale à 0,00001 ou moins encore.

    Cette gestion d'arrondi n'est pas spécifique à WinDev/WebDev/WinDev Mobile. Elle est générale à tous les langages manipulant des réels sous forme binaire.

    Code WLangage : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Diff, R1, R2 sont des réels
    Diff = 0.00001
    SI Abs(1-(R1/R2)) < Diff ALORS
            // R1 et R2 sont égaux
    SINON
            // R1 et R2 sont différents
    FIN
    Pour ma part, je ne trouve pas du tout "intuitif" que l'opérateur = soit bridé à 6 décimales au motif qu'un nombre à virgule flottante peut être une "approximation" du nombre réel qu'il représente.

    Ce choix est propre à Windev et au WLangage, et ne se retrouve pas dans les autres langages de programmation comme le C, Pascal etc.

    Ainsi le bridage de l'opérateur = sur le nombre 1.2 par exemple implique que pour le WLangage
    1.2 = 1.199999
    alors que pour les autres langages, l'approximation implique seulement
    1.2 = 1.1999999999999999

    Il y a quand même une différence conséquente.

    On arrive a des aberrations quand le bridage est appliqué à des littéraux (exemple donné par DelphiManiac: 0.0000001 = 0.00), c'est un non sens pour le commun des développeurs.

    On trouve plus d'information en lisant la page qui présente le type "Réels":
    http://doc.pcsoft.fr/fr-FR/?1514048

    On y apprend que la représentation d'un Réel sous forme textuelle en base 10 tient compte de l'approximation inhérente au nombre à virgule flottante.

    Le codage du nombre 1.2 en virgule flottante est :
    1.2000000476837158203125 sur 32 bits (réel sur 4 octets)
    1.1999999999999999555910790149937383830547 sur 64 bits (réel sur 8 octets)

    Mais dans les deux cas, la représentation textuelle en base 10 du nombre est bien:
    "1.2"

    Je me suis intéressé à la fonction PartieDécimale qui retourne la partie décimale d'un Réel.

    Pour le nombre 1.2, j'ai pu constater que la fonction PartieDécimale tient compte de l'approximation dans le cas d'un nombre réel sur 8 octets et retourne:
    0.2

    En revanche, ce n'est pas vrai pour un réel sur 4 octets pour lequel cette fonction retourne:
    0.2000000476837

    Aussi, je me demande quelles sont les fonctions et opérateurs du WLangage qui gèrent l'approximation sur les réels et si c'est homogène selon que le réel est sur 4 ou 8 octets ?

    Dans le cas de la fonction PartieDécimale appliquée au réel 1.2, on voit que l'approximation est gérée pour un réel sur 8 octets, mais pas sur 4 octets.

  6. #26
    Membre éclairé
    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    303
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 303
    Points : 812
    Points
    812
    Par défaut
    Citation Envoyé par DelphiManiac Voir le message

    Ce code là est pour le moins perturbant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SI 0.0000001 = 0.00 ALORS
    	Trace("égal")
    SINON
    	Trace("différent")
    FIN
    Devinez le résultat
    Le résultat est:

    "égal"

    Pour éviter ce bridage de l'opérateur = sur les nombres réels (ici littéraux), on peut forcer le type des littéraux en numérique (même un seul suffit).
    Les tests ci-dessous ont tous pour résultat : "différent".

    SI 0n0.0000001 = 0n.00 ALORS.
    SI 0n0.0000001 = 0.00 ALORS.
    SI 0.0000001 = 0n0.00 ALORS.

  7. #27
    Membre émérite
    Avatar de DelphiManiac
    Homme Profil pro
    Homme à tout faire
    Inscrit en
    Mars 2002
    Messages
    1 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Homme à tout faire
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 147
    Points : 2 533
    Points
    2 533
    Par défaut
    Pour éviter ce bridage de l'opérateur = sur les nombres réels (ici littéraux)
    Ce n'est pas un bridage, mais une aberration, ni plus ni moins. Surtout que le "compilateur" n'indique même pas un warning.

    0.0000001 est différent de 0.0 quelque soit le contexte dans lequel on se place encore plus quand c'est écrit en littéral.

    Même dans un contexte "intuitif" comme quelqu'un l'indique dans un message, cela reste complètement erroné.

    J'avais trouvé la page de documentation parlant de cette pseudo fonctionnalité après avoir posté. Donc cela a au moins le mérite d'être documenté. Par contre, aucune possibilité de désactiver ce mode de fonctionnement :/

    Ce sujet aura au moins eu le mérite de faire découvrir, à certain, les pièges liés au nombre flottant en informatique

    Sinon, beau développement, bien mieux expliqué que moi
    Si ce message vous a semblé utile, il est possible qu'il soit utile à d'autres personnes. Pensez au . Et n'oubliez pas le le moment venu !

    On n'a pas à choisir si l'on est pour ou contre la décroissance, elle est inéluctable, elle arrivera qu'on le veuille ou non.

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. Afficher des lignes qui n'ont pas de résultat
    Par Nessie37 dans le forum Requêtes et SQL.
    Réponses: 2
    Dernier message: 25/10/2007, 16h11
  2. Réponses: 3
    Dernier message: 21/11/2006, 18h26
  3. Réponses: 4
    Dernier message: 08/06/2006, 13h18
  4. la liste des clients qui n'ont pas acheter aucun article ...
    Par TéBeSsI dans le forum Langage SQL
    Réponses: 6
    Dernier message: 13/02/2004, 14h57

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