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 6 et antérieur Discussion :

CDbl(CSng("0,3")) = 0,300000011920929 ?!? [Trucs & Astuces]


Sujet :

VB 6 et antérieur

  1. #1
    Membre averti
    Homme Profil pro
    Développeur VB6 et tout neuf en .Net
    Inscrit en
    Avril 2005
    Messages
    377
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France

    Informations professionnelles :
    Activité : Développeur VB6 et tout neuf en .Net
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2005
    Messages : 377
    Points : 446
    Points
    446
    Par défaut CDbl(CSng("0,3")) = 0,300000011920929 ?!?
    Bonjour à tous,

    Quelqu'un aurait-il une explication, voir une solution à ce problème :
    CDbl(CSng("0,3")) = 0,300000011920929 et pas 0,3
    CDbl(CSng("567,27")) = 567,27001953125 et pas 567,27

    Cela ressemble à un bug de VB6, non ?

    Merci d'avance
    Le plus difficile pour trouver une bonne réponse, c'est déjà de trouver la bonne question.

  2. #2
    Modérateur
    Avatar de ProgElecT
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2004
    Messages
    6 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Décembre 2004
    Messages : 6 077
    Points : 17 174
    Points
    17 174
    Par défaut
    je pense que s'est dans l'ordre de la conversion, comme sa le resultat est bon
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Label1 = CSng(CDbl("0,3")) '= 0,3
    Label2 = CSng(CDbl("567,27")) '= 567,27
    mais pourquoi , moi je ne sais pas.
    Soyez sympa, pensez -y
    Balises[CODE]...[/CODE]
    Balises[CODE=NomDuLangage]...[/CODE] quand vous mettez du code d'un autre langage que celui du forum ou vous postez.
    Balises[C]...[/C] code intégré dans une phrase.
    Balises[C=NomDuLangage]...[/C] code intégré dans une phrase quand vous mettez du code d'un autre langage que celui du forum ou vous postez.
    Le bouton en fin de discussion, quand vous avez obtenu l'aide attendue.
    ......... et pourquoi pas, pour remercier, un pour celui/ceux qui vous ont dépannés.
    👉 → → Ma page perso sur DVP ← ← 👈

  3. #3
    Membre averti
    Homme Profil pro
    Développeur VB6 et tout neuf en .Net
    Inscrit en
    Avril 2005
    Messages
    377
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France

    Informations professionnelles :
    Activité : Développeur VB6 et tout neuf en .Net
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2005
    Messages : 377
    Points : 446
    Points
    446
    Par défaut
    Citation Envoyé par ProgElecT
    je pense que s'est dans l'ordre de la conversion, comme sa le resultat est bon.
    Effectivement, mais mon objectif est de transformer un Single en Double et pas l'inverse...

    Au moins, je sais maintenant que cela ne vient pas mon ordinateur.

    Merci quand même
    Le plus difficile pour trouver une bonne réponse, c'est déjà de trouver la bonne question.

  4. #4
    Expert confirmé
    Avatar de zazaraignée
    Profil pro
    Étudiant
    Inscrit en
    Février 2004
    Messages
    3 174
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2004
    Messages : 3 174
    Points : 4 085
    Points
    4 085
    Par défaut
    C'est par ce que tu commence par transformer une chaîne (String) en Single, puis ce Single en Double... Plus il y a de manipulations plus il s'accumule d'erreurs. Si tu convertis directement
    tu n'as plus de problème!

    Si tu cherches à convertir en Double le contenu d'un TextBox :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Debug.Print CDbl(Val(Text1.Text))
    Voilà!

  5. #5
    Membre averti
    Homme Profil pro
    Développeur VB6 et tout neuf en .Net
    Inscrit en
    Avril 2005
    Messages
    377
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France

    Informations professionnelles :
    Activité : Développeur VB6 et tout neuf en .Net
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2005
    Messages : 377
    Points : 446
    Points
    446
    Par défaut
    Le code suivant était un exemple pour mettre en évidence le problème :
    Je cherche "simplement" à convertir un Single en Double.
    Je sais simplement, qu'avant, quelque part dans le déroulement du programme, ce Single provient d'une zone de texte.
    Le programme étant vaste, je dois prendre le single tel qu'il est sans me soucier de sa provenance, ni de son vécu.
    Je suppose que le programme n'est pas en cause car CDbl(CSng("0,3")) renvoi 0,300000011920929 dans la fenêtre d'éxécution.
    Le plus difficile pour trouver une bonne réponse, c'est déjà de trouver la bonne question.

  6. #6
    Expert confirmé
    Avatar de zazaraignée
    Profil pro
    Étudiant
    Inscrit en
    Février 2004
    Messages
    3 174
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2004
    Messages : 3 174
    Points : 4 085
    Points
    4 085
    Par défaut
    On peut voir comment la fonction de conversion est déclarée, décrite, avec ses paramètres... ?

  7. #7
    Membre expert Avatar de OhMonBato
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    2 660
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2007
    Messages : 2 660
    Points : 3 685
    Points
    3 685
    Par défaut
    C'est le problème des calculs avec des virgules flottantes je crois, si je ne dis pas de betise, ca tient plus du processeur que de VB.
    En tout cas tu peux palier à ton pb en mettant par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CDbl(Format(CSng(0.3), "0.0000000000000000"))
    Pas terrible terrible, mais ça fonctionne.
    Pour VB6 : N'oubliez pas d'aller voir la FAQ et les Tutoriels
    Vous trouvez une reponse particulierement utile ? Votez pour !

  8. #8
    Membre averti
    Homme Profil pro
    Développeur VB6 et tout neuf en .Net
    Inscrit en
    Avril 2005
    Messages
    377
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France

    Informations professionnelles :
    Activité : Développeur VB6 et tout neuf en .Net
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2005
    Messages : 377
    Points : 446
    Points
    446
    Par défaut
    Je pense que le problème est spécifique à la conversion Single vers Double car :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CDbl(CStr(CSng("0,3"))) = 0,3
    Je pense que je vais adopter cette solution ici faute de mieux...

    Ce qui m'inquiète c'est pour tout le reste du programme où je n'est pas encore détecté le problème...
    Le plus difficile pour trouver une bonne réponse, c'est déjà de trouver la bonne question.

  9. #9
    Expert confirmé
    Avatar de zazaraignée
    Profil pro
    Étudiant
    Inscrit en
    Février 2004
    Messages
    3 174
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2004
    Messages : 3 174
    Points : 4 085
    Points
    4 085
    Par défaut
    Citation Envoyé par Najdar
    Je sais simplement, qu'avant, quelque part dans le déroulement du programme, ce Single provient d'une zone de texte.
    Citation Envoyé par zazaraignée
    On peut voir comment la fonction de conversion est déclarée, décrite, avec ses paramètres... ?
    Car, si j'ai bien compris, tu essaie de créer une fonction de conversion qui soit applicable à une valeur, peu importe sa provenance et son type, tout en conservant un format déterminé.

  10. #10
    Membre averti
    Homme Profil pro
    Développeur VB6 et tout neuf en .Net
    Inscrit en
    Avril 2005
    Messages
    377
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France

    Informations professionnelles :
    Activité : Développeur VB6 et tout neuf en .Net
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2005
    Messages : 377
    Points : 446
    Points
    446
    Par défaut
    En essayant de faire court :

    Je stocke dans une property d'une classe des valeurs provenant de diverses sources et de types différents:
    - saisies à l'écran et bases de données.
    - Single, Double, Long, ...
    Je sais que ces valeurs sont toujours des numériques, j'ai donc choisi Double pour être sûr que tous les types "tiennent".

    Le problème se pose quand j'affecte à cette property une valeur de type Single.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Private mValeur(1 To 4)         As Double
     
    Public Property Get Valeur(ByVal Index As Integer) As Double
      Valeur = mValeur(Index)
    End Property
    Public Property Let Valeur(ByVal Index As Integer, ByVal vNewValue As Double)
        mValeur(Index) = vNewValue
    End Property
    Pour que cela fonctionne correctement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Private mValeur(1 To 4)         As Double
     
    Public Property Get Valeur(ByVal Index As Integer) As Variant
      Valeur = mValeur(Index)
    End Property
    Public Property Let Valeur(ByVal Index As Integer, ByVal vNewValue As Variant)
      If TypeName(vNewValue) = "Single" Then
        mValeur(Index) = CDbl(CStr(vNewValue))
      Else
        mValeur(Index) = CDbl(vNewValue)
      End If
    End Property
    Cela n'est pas terrible, et l'utilisation d'un Variant ne me plait pas
    Le plus difficile pour trouver une bonne réponse, c'est déjà de trouver la bonne question.

  11. #11
    Expert confirmé
    Avatar de zazaraignée
    Profil pro
    Étudiant
    Inscrit en
    Février 2004
    Messages
    3 174
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2004
    Messages : 3 174
    Points : 4 085
    Points
    4 085
    Par défaut
    Heu... Un currency ne tiendra pas dans un Double.

    Pour le reste, je suis lagruée! Je m'attendais à voir une Fonction et tu m'envoies une Propriété.

    Il te sera difficile de traiter n'importe quoi venant de n'importe où sans provoquer des erreurs!

  12. #12
    Membre expert
    Avatar de Delbeke
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    2 675
    Détails du profil
    Informations personnelles :
    Âge : 70
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 2 675
    Points : 3 696
    Points
    3 696
    Par défaut
    Ben au contraire je trouve l'idée bonne moi

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Public Property Let Valeur(ByVal Index As Integer, ByVal vNewValue As Variant)
      Dim strTemp as string
      Dim iPosit as Integer
      strTemp = Cstr(vNewValue)
      iPosit = instrRev(strTemp,",")
      if iPosit then
        Mid(strTemp,iPosit,1)= "."
      end if
      mValeur(Index) = CDbl(strTemp)
    End Property
    En général, on ne demande de conseils que pour ne pas les suivre ou, si on les a suivis, reprocher à quelqu'un de les avoir donnés
    (ALEXANDRE DUMAS)

    N'hésitez pas à visiter ma page de contributions

  13. #13
    Membre à l'essai
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2007
    Messages : 8
    Points : 10
    Points
    10
    Par défaut Explication technique
    Le problème vient de la conversion d'un single en double et cela ne vient pas du processeur, mais bien de VB.

    Les nombres réels ou flottants sont décomposés en trois parties :
    - S : le signe du nombre ;
    - M : la mantisse ou significande ;
    - E : l'exposant.

    En faisant varier E, on fait "flotter" la virgule, d'où l'appellation de nombre flottant.

    Regardons comment sont codé en binaire les nombres réel ou flottants :

    Désignation Taille Signe Exposant Mantisse
    Single 32 bits 1 bit 8 bits 23 bits
    Double 64 bits 1 bit 11 bits 52 bits

    Pour retrouver la valeur d'un nombre en simple précision, il faut faire :
    (-1)^S*(1+M)*2^(E-127)
    Ou, pour les nombres en double précision :
    (-1)^S*(1+M)*2^(E-1023)

    Si bien que si l'on représente notre nombre (1.1) en binaire, on obtient les représentations suivantes :
    0011 1111 1000 1100 1100 1100 1100 1101 (3F 8C CC CD)
    et
    0011 1111 1111 0001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1010 (3F F1 99 99 99 99 99 9A)

    Hors pour des raison de rapidité, Visual Basic ne recalcul ni l'exposant ni la mantisse lors d'une conversion d'un single en double, mais se contente de rajouter trois 1 à la fin de l'exposant et des 0 à la fin de la mantisse.

    Notre 1,1 (single) converti en double devient donc :
    0011 1111 1111 0001 1001 1001 1001 1001 1010 0000 0000 0000 0000 0000 0000 0000 (3F F1 99 99 A0 00 00 00)

    Si l'on exprime ce nombre en décimale on obtient 1,1000000238418580. Ce qui n'est plus tout à fait 1,1.


    La multiplication par 2 peut se résumer par l'adition de 1 à l'exposant.
    0100 0000 0000 0001 1001 1001 1001 1001 1010 0000 0000 0000 0000 0000 0000 0000
    40019999a0000000
    Ce qui donne 2.2000000476837160 en décimal.

  14. #14
    Membre expert
    Avatar de Delbeke
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    2 675
    Détails du profil
    Informations personnelles :
    Âge : 70
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 2 675
    Points : 3 696
    Points
    3 696
    Par défaut
    Belle démonstration
    En général, on ne demande de conseils que pour ne pas les suivre ou, si on les a suivis, reprocher à quelqu'un de les avoir donnés
    (ALEXANDRE DUMAS)

    N'hésitez pas à visiter ma page de contributions

Discussions similaires

  1. Quote et double quote
    Par aktos dans le forum Langage
    Réponses: 8
    Dernier message: 05/01/2007, 19h55

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