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

Langage Delphi Discussion :

double, single, différences et chiffres farfelus


Sujet :

Langage Delphi

  1. #1
    Nouveau membre du Club
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2007
    Messages
    55
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2007
    Messages : 55
    Points : 28
    Points
    28
    Par défaut double, single, différences et chiffres farfelus
    Bonjour

    Je viens de me prendre la tête sérieusement avec un problème de nombre décimal et les inventions de chiffres derrière la virgule par Delphi.

    Je dois ré-écrire des calculs Delphi en PL/SQL (Oracle). Je fais une procédure stockée permettant de comparer les résultats obtenus par les 2 méthodes (résultats stockés dans 2 tables Oracle différentes).
    Et j'ai des petites différences... Je débuggue, analyse les valeurs et là, je tombe sur 1.39999997. Hein ???
    On a une fonction Delphi qui renvoie un single, qui fait tout un tas de calcul et qui renvoie 1.3, 1.4, 1.5... dans ce style-là, directement, sans calcul. Et dans une autre fonction on stocke dans un single le résultat de cette 1ère fonction : 1.3999... RoundTo : pareil ! Autres trucs équivalent : même valeur ! Je multiplie par 10, je passe par un entier. Pas mieux ! Je prend un 2ème single dans lequel je met entier/10 et encore la valeur bidon

    Je cherche sur le forum, je trouve des problèmes +/- semblables à la pelle mais je trouve la solution tout seul : j'ai mis un double pour ma variable qui reçoit le résultat de ma fonction en single et ça fonctionne.


  2. #2
    Membre expert
    Avatar de e-ric
    Homme Profil pro
    Apprenti chat, bienfaiteur de tritons et autres bestioles
    Inscrit en
    Mars 2002
    Messages
    1 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Apprenti chat, bienfaiteur de tritons et autres bestioles

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 559
    Points : 3 948
    Points
    3 948
    Par défaut
    Salut

    Les nombres en virgule flottante sont par nature imprécis puisqu'ils sont une approximation avec un nombre fixé de bits, cela permet d'avoir des nombres avec un encombrement limité et des calculs dans un temps raisonnable.

    Attention, si je me souviens bien, Oracle emploie une représentation en BCD, dans laquelle chaque demi-octet est un chiffre de 0 à 9 et le nombre de décimales est fixé, cela est moins efficace car les processeurs Intel ne supportent pas nativement cette représentation.

    Delphi 7 dispose d'une bibliothèque d'émulation pour les BCD mais bof... elle est boguée.

    @+

    M E N S . A G I T A T . M O L E M
    Debian 64bit, Lazarus + FPC -> n'oubliez pas de consulter les FAQ Delphi et Pascal ainsi que les cours et tutoriels Delphi et Pascal

    "La théorie, c'est quand on sait tout, mais que rien ne marche. La pratique, c'est quand tout marche, mais qu'on ne sait pas pourquoi. En informatique, la théorie et la pratique sont réunies: rien ne marche et on ne sait pas pourquoi!".
    Mais Emmanuel Kant disait aussi : "La théorie sans la pratique est inutile, la pratique sans la théorie est aveugle."

  3. #3
    Nouveau membre du Club
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2007
    Messages
    55
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2007
    Messages : 55
    Points : 28
    Points
    28
    Par défaut
    Cela faisait longtemps que je n'avais pas eu de problème de précision avec Delphi. Mettre 1.4 "en dur" dans une variable, et l'évaluer directement avec 1.39999997, c'est lamentable ! Rien qu'un détail comme celui-là, qui se contourne +/- bien, je serais chef de projet dans une banque : ce serait delphi ou moi !
    Vous ne savez pas le pire ? Le programme fait un FinKey sur une table de paramétrage et il trouve un enregistrement ! Il va chercher le paramétrage 1.3 au lieu du 1.4.
    On appelle ça déterrer des cadavres : on balance des informations fausses depuis des années sans que personne n'y aie vu quoi que ce soit.

  4. #4
    Membre éprouvé

    Profil pro
    Inscrit en
    Mai 2003
    Messages
    582
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Mai 2003
    Messages : 582
    Points : 915
    Points
    915
    Par défaut
    Citation Envoyé par alf_idsoft Voir le message
    je serais chef de projet dans une banque : ce serait delphi ou moi !
    Peu importe le langage de programmation, vous aurez à vivre avec ce genre de problème. Pour comparer 2 nombres en virgule flottante, on doit les soustraitres et comparer avec une tolérence.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Function CompareFloat(a: single; b: single; Epsi: single = 0.001): boolean;
    Begin
      result := abs(a - b) < Epsi;
    End;
    Comment dupliquer un disque...ça vous intéresse?
    Tutoriel et code source delphi ici

  5. #5
    Nouveau membre du Club
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2007
    Messages
    55
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2007
    Messages : 55
    Points : 28
    Points
    28
    Par défaut
    ça me rappelle quand je m'amusais sur ma (calculatrice) TI85, j'étais confronté à cette marge d'erreur.
    La, c'est bien + grave, on stocke 1.4 en dur dans une variable et on lui demande aussitôt combien elle vaut et c'est différent.
    Je suis loin d'avoir fait le tour de tous les langages, j'ai toujours bien apprécié Delphi, mais je n'ai jamais vu ça ailleurs

  6. #6
    Membre éprouvé

    Profil pro
    Inscrit en
    Mai 2003
    Messages
    582
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Mai 2003
    Messages : 582
    Points : 915
    Points
    915
    Par défaut
    La problèmatique est bien démontrée ici

    http://cpp.developpez.com/redaction/...ant/flottant1/

    Bonne Lecture
    Comment dupliquer un disque...ça vous intéresse?
    Tutoriel et code source delphi ici

  7. #7
    Membre expert
    Avatar de e-ric
    Homme Profil pro
    Apprenti chat, bienfaiteur de tritons et autres bestioles
    Inscrit en
    Mars 2002
    Messages
    1 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Apprenti chat, bienfaiteur de tritons et autres bestioles

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 559
    Points : 3 948
    Points
    3 948
    Par défaut
    Comme le dit Eric Boisvert, ce n'est pas un problème de langage, C aurait le même problème (Delphi est hors de cause ), lié à la représentation des nombres en virgule flottante.

    Petite parenthèse "méthodoloqique" : définir une clé de recherche avec un champ en virgule flottante, c'est pas fier et c'est prendre des risques, la preuve!! Il me semble que FindKey peut faire une recherche sur un intervalle sous certaines conditions mais c'est à vérifier, ça fait longtemps que je n'ai pas regardé ça. En tenant compte des remarque d'Eric, il y a alors moyen de faire.

    @+

    M E N S . A G I T A T . M O L E M
    Debian 64bit, Lazarus + FPC -> n'oubliez pas de consulter les FAQ Delphi et Pascal ainsi que les cours et tutoriels Delphi et Pascal

    "La théorie, c'est quand on sait tout, mais que rien ne marche. La pratique, c'est quand tout marche, mais qu'on ne sait pas pourquoi. En informatique, la théorie et la pratique sont réunies: rien ne marche et on ne sait pas pourquoi!".
    Mais Emmanuel Kant disait aussi : "La théorie sans la pratique est inutile, la pratique sans la théorie est aveugle."

  8. #8
    Nouveau membre du Club
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2007
    Messages
    55
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2007
    Messages : 55
    Points : 28
    Points
    28
    Par défaut
    Oh punaise
    Donc rien ne dit que je ne ferai pas avoir de la même manière sur un autre langage dans 10 ans
    Un floatword de 0 à 655.35 et j'aurai été content

  9. #9
    Nouveau membre du Club
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2007
    Messages
    55
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2007
    Messages : 55
    Points : 28
    Points
    28
    Par défaut
    Honnêtement, je ne me rappelle pas avoir utilisé findkey (ce n'est pas moi qui avait codé), cela m'a carrément étonné qu'il fonctionnait avec ce nombre bancal
    Je remplace du Delphi par du Oracle et je dois malheureusement corriger des détails dans le programme d'origine pour pouvoir correctement blinder les résultats : s'il y a une différence à la fin, soit j'ai mal retranscrit, soit j'ai corrigé malgré moi un bug en changeant de langage.
    Changer un findkey par un locate... cela ne sert à rien puisque le programme Delphi ne sera plus utilisé

  10. #10
    Membre éprouvé

    Profil pro
    Inscrit en
    Mai 2003
    Messages
    582
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Mai 2003
    Messages : 582
    Points : 915
    Points
    915
    Par défaut cela ce peut un bug dans delphi....mais....
    Mon avis à tous...

    Lorsque vous croyez qu'il y a un bug dans un langage quelconque....
    Je vous invite à approfondir la problématique en question....

    C'est habituellement un concept mal compris qui vous attend...

    Un vrais bug dans un langage est habituellement relié à un contexte très
    particulier... et de ce fait... seulement quelque malchanceux tombe dessus...
    sinon, le distributeur du logiciel émet habituellement rapidement, une mise à jour de son produit....

    (Cette mise en garde déborde largement le sujet en cours bien sûre)

    Désolé... c'était plus fort que moi.
    Comment dupliquer un disque...ça vous intéresse?
    Tutoriel et code source delphi ici

  11. #11
    Nouveau membre du Club
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2007
    Messages
    55
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2007
    Messages : 55
    Points : 28
    Points
    28
    Par défaut
    C'est bien de le dire
    Depuis le temps que je suis dans le métier, se pourrir une matinée pour un réel approximatif, ça agace et c'est vrai que la 1ère réaction (pas seulement la mienne au boulot), c'était de râler sur Delphi.
    Rien à voir avec le sujet, mais il y a des bugs en Delphi : je suis resté à la version 7, mais rien qu'un recordcount, ça ne fonctionne pas terrible. Je n'ai jamais creusé pourquoi c'était comme cela, juste toujours fait autrement.

  12. #12
    Membre expert
    Avatar de e-ric
    Homme Profil pro
    Apprenti chat, bienfaiteur de tritons et autres bestioles
    Inscrit en
    Mars 2002
    Messages
    1 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Apprenti chat, bienfaiteur de tritons et autres bestioles

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 559
    Points : 3 948
    Points
    3 948
    Par défaut
    Pourtant les problèmes liés aux nombres en virgule flottante ne sont pas nouveaux... C, C++ et tous les langages qui s'appuient sur la représentation native des processeurs en micro auront les mêmes soucis. Une solution consisterait à mettre en place sa propre représentation des nombres, mais bonjour le travail et il vaut mieux être fort en maths.

    C'est Intel et AMD à qui il faut demander des comptes, les langages de programmation ne font que se plier à ce qu'offrent les processeurs.

    Quant au Recordcount, il faut lire la doc, ce qui inclut les sources de la VCL (TDataSet par exemple). Il faut savoir que les SGBD n'offrent pas les mêmes solutions face au même problème, disons que RecordCount en fait partie et qu'il est mis en place à l'origine pour les tables Paradox. Pour les bases Access, à une époque je ne sais si c'est encore valable, il fallait exécuter Dataset.Last avant de connaître la bonne valeur de RecordCount. C'est une fonctionnalité qu'il vaut mieux bannir surtout dans un environnement concurrentiel (aui sens de la base de données).

    Quand une fonctionnalité ne marche pas idéalement, cela peut être un bug mais pas toujours...

    Cdlt

    M E N S . A G I T A T . M O L E M
    Debian 64bit, Lazarus + FPC -> n'oubliez pas de consulter les FAQ Delphi et Pascal ainsi que les cours et tutoriels Delphi et Pascal

    "La théorie, c'est quand on sait tout, mais que rien ne marche. La pratique, c'est quand tout marche, mais qu'on ne sait pas pourquoi. En informatique, la théorie et la pratique sont réunies: rien ne marche et on ne sait pas pourquoi!".
    Mais Emmanuel Kant disait aussi : "La théorie sans la pratique est inutile, la pratique sans la théorie est aveugle."

  13. #13
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Pour le RecordCount, je confirme sous DBExpress + Sybase, il ne fonctionne quasiment jamais !
    En BCB2007, j'avais quelques cas basiques qui passait, je crois que j'en ai encore moins depuis XE2 mais la documentation de DBExpress prévient que RecordCount est capricieux !

    On en a rarement besoin, une boucle sur EOF\Next suffit mais cela empêche des optimisations comme pré-allouer un tableau par exemple ou utiliser Capacity d'une TList

    Pour les erreurs d'arrondis sur les valeurs à virgule flottante, un débat qui revient souvent !
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

Discussions similaires

  1. Double tagging : différence entre 802.1q et 802.1ad
    Par boboss123 dans le forum Protocoles
    Réponses: 2
    Dernier message: 20/11/2012, 08h50
  2. Réponses: 2
    Dernier message: 10/09/2006, 12h35
  3. Obtenir une différence d'heure modulo un chiffre
    Par n@n¤u dans le forum Requêtes
    Réponses: 1
    Dernier message: 23/06/2006, 10h20
  4. Différence entre Integer et double?
    Par Michel DELAVAL dans le forum Access
    Réponses: 15
    Dernier message: 10/02/2006, 15h57
  5. [VB.NET]Comment obtenir conversion exacte Single>Double?
    Par Misterburma dans le forum VB.NET
    Réponses: 9
    Dernier message: 09/02/2006, 22h24

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