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

 C++ Discussion :

Peut on contourner la troncature float vers int?


Sujet :

C++

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2006
    Messages : 134
    Points : 61
    Points
    61
    Par défaut Peut on contourner la troncature float vers int?
    Bonjour, j'aimerai savoir s'il est possible d'éviter la troncature lors de la conversion d'un float vers un int. Mon but est de retrouver ma valeur de départ sans aucune perte information. Est ce que c'est possible? Il existe un astuce a connaitre comme passer par des chaines de caractère?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    int a=2147483647;
    float b=0;
    int c=0;
    b=a;
    c=(int)b;
    Merci d'avance pour vos réponses.

  2. #2
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 533
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 533
    Points : 6 709
    Points
    6 709
    Par défaut
    que voulez-vous dire par là ?
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2006
    Messages : 134
    Points : 61
    Points
    61
    Par défaut
    Citation Envoyé par bruno_pages Voir le message
    que voulez-vous dire par là ?
    Mauvais clic désolé j'ai modifier mon message. Je suis un utilisateur occasionnel de bouml très pratique et utile comme programme.

  4. #4
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    Il semblerait que quelques mots soient restés coincés dans le clavier, et je présumes donc que ta phrase termine par "conversion d'un float en int"

    La réponse est non, tout simplement parce que int ne peut représenter que des valeurs entières.

    Par contre, il est possible de demander un arrondi, suivant les règles mathématique (à l'unité inférieur si la partie décimale est inférieure à 5, à l'unité supérieure autrement), à l'unité supérieure en toutes circonstances ou à l'unité inférieure (ce qui revient au même que la troncature) en toutes circonstances avec les fonctions respectives round, ceill et floor.
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  5. #5
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 533
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 533
    Points : 6 709
    Points
    6 709
    Par défaut
    la troncature n'a pas lieu lors du passage float -> int, elle a lieu lors du passage int -> float , car 2147483647 réclame plus que 23 bits pour être représenté

    remplacez le float par un double et il n'y aura pas de problème de précision
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2006
    Messages : 134
    Points : 61
    Points
    61
    Par défaut
    Salut, je vois les fonctions dont tu parle tel que floor et ceil de <math.> pour faire des arrondis mais est ce qu'il serait possibles par un moyen ou un autre de ne garder que la partie entière lors du passage int -> float ->int. Je me disait en récupérant dans une chaine de caractère la partie entière du float peut on pourrait retomber sur nos pattes?

    Citation Envoyé par koala01 Voir le message
    Salut,

    Il semblerait que quelques mots soient restés coincés dans le clavier, et je présumes donc que ta phrase termine par "conversion d'un float en int"

    La réponse est non, tout simplement parce que int ne peut représenter que des valeurs entières.

    Par contre, il est possible de demander un arrondi, suivant les règles mathématique (à l'unité inférieur si la partie décimale est inférieure à 5, à l'unité supérieure autrement), à l'unité supérieure en toutes circonstances ou à l'unité inférieure (ce qui revient au même que la troncature) en toutes circonstances avec les fonctions respectives round, ceill et floor.

  7. #7
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 533
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 533
    Points : 6 709
    Points
    6 709
    Par défaut
    que de réponses simultanées => lire ma précédente réponse
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

  8. #8
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Le fait est que la partie entière sera la partie la plus stable (du moins dans les limites des valeurs représentables) lors des conversions:
    0.9 en float ou en double donnera 0 (si on n'utilise pas round ou ceil) en int et 0 en int donnera.... 0. 00000 en float ou en double (idem pour 12540.xxxxx).

    Ce qui est plus embêtant, c'est que si tu converti un float en int, que ce soit avec troncature ou avec arrondi, puis que tu reconverti ce int en float, tu perd, purement et simplement, la partie décimale
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2006
    Messages : 134
    Points : 61
    Points
    61
    Par défaut
    Citation Envoyé par bruno_pages Voir le message
    la troncature n'a pas lieu lors du passage float -> int, elle a lieu lors du passage int -> float , car 2147483647 réclame plus que 23 bits pour être représenté

    remplacez le float par un double et il n'y aura pas de problème de précision
    Cette troncature dans ce sens la int -> float ne me dérange pas c'est celle dans l'autre sens float -> int qui me pose problème de plus je travaille avec des données codées sur 64bit( int64 -> float64-> int64 ). Je suppose que c'est le même problème avec des entier sur 32 bits
    Si je rentre la valeur maximum et minimum en entrer j'obtiens le même résultat au final.

    int64 -> float64-> int64
    min -9223372036854775808 -> -9223372036854775808
    max 9223372036854775807 -> -9223372036854775808

    Je devine bien que -9223372036854775808 correspond à la partie entière de mon float qui doit être 7FFF FFFF. Est ce qu'il existe une moyen de tricher lors du passage float -> int pour retourner au résultat du début.

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2006
    Messages : 134
    Points : 61
    Points
    61
    Par défaut
    Pour vous donner une id de ce que j'essaye de faire, je travail avec un float64 dont j'ai supposé à tord qu'il pouvait contenir tout les autres types ensuite j'effectue une conversion d'où celle qui m'intéresse float64 vers int64

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    void* _elementPtr;
    float64_t fValue;
        switch (_dataInfo.type)
        {
        case I16:
          *(int16_t*)_elementPtr = (int16_t) fValue;
          break;
        case I32:
          *(int32_t*)_elementPtr = (int32_t) fValue;
          break;
        case I64:
          *(int64_t*)_elementPtr = (int64_t) fValue;
          break;
        case F32:
          *(float32_t*)_elementPtr = (float32_t) fValue;
          break;
        case F64:
          *(float64_t*)_elementPtr = (float64_t) fValue;
          break;
        }
    Lors de mes test avec mes valeurs max pour chaque type je constate que le passage float64 vers int64 échoue. C'est tout bête comme problème mais sa arrive.
    Merci pour votre aide.

  11. #11
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 533
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 533
    Points : 6 709
    Points
    6 709
    Par défaut
    vous n'avez pas compris, c'est un problème de précision, et cela arrive lors du passage entier -> réel

    à taille égale un réel est par définition moins précis qu'un entier car il faut stoker la mantisse et le signe (problème du signe uniquement si l'entier est non signé et récupère donc ce bit)
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

  12. #12
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Si le float64 n'est qu'un stockage intermédiaire et que la valeur qui se retrouve dedans ne t'intéresse pas, tu peux simplement utiliser ses 64 bits sans tenir compte du fait que c'est un flottant. C'est en quelque sorte le mécanisme inverse de la fonction que tu nous as montré, qui restitue la valeur dans une variable en fonction du type interne.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    *reinterpret_cast<int64_t*>(&fValue) = le_int_64;
    D'ailleurs là tu peux prendre un char[8] plutôt qu'un float64, puisque tout ce qui t'intéresse sera d'avoir un espace mémoire de 64 bits.
    Et si tu fais ça, assure-toi bien qu'aucun des types que tu gères ne dépasse 64 bits.

  13. #13
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 533
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 533
    Points : 6 709
    Points
    6 709
    Par défaut
    ou bien-sûr utiliser une union
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

  14. #14
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2006
    Messages : 134
    Points : 61
    Points
    61
    Par défaut
    Ok j'ai saisie la perte de précision, après réflexion c'est normal. Je me pose alors comme question qu'elles sont les valeurs maximum et minimum pour mon int64 pour que le passage int64 -> float64 -> int64 fonctionne. La limitation serait donc égale au maximum et au minimum que je peut coder sur la partie entière de mes float 64bits.

    Merci pour votre j'utilise bouml et mingw et mine de rien vos aides sont super utiles et super bien faites.

  15. #15
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mars 2006
    Messages : 134
    Points : 61
    Points
    61
    Par défaut
    Super comme idée, je vais voir si je peut la mettre en œuvre vu que je fait quelques opérations sur mon float64.

    Citation Envoyé par Laurent Gomila Voir le message
    Si le float64 n'est qu'un stockage intermédiaire et que la valeur qui se retrouve dedans ne t'intéresse pas, tu peux simplement utiliser ses 64 bits sans tenir compte du fait que c'est un flottant. C'est en quelque sorte le mécanisme inverse de la fonction que tu nous as montré, qui restitue la valeur dans une variable en fonction du type interne.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    *reinterpret_cast<int64_t*>(&fValue) = le_int_64;
    D'ailleurs là tu peux prendre un char[8] plutôt qu'un float64, puisque tout ce qui t'intéresse sera d'avoir un espace mémoire de 64 bits.
    Et si tu fais ça, assure-toi bien qu'aucun des types que tu gères ne dépasse 64 bits.

  16. #16
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    je veux pas casser l'ambiance, mais de mémoire déréférencer un pointeur issu d'un reinterpret_cast est une Undefined Behavior.

  17. #17
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    L'union me semble être la solution la plus évidente étant donné ce qu'on sait du problème.

    Citation Envoyé par Joel F Voir le message
    je veux pas casser l'ambiance, mais de mémoire déréférencer un pointeur issu d'un reinterpret_cast est une Undefined Behavior.
    Il me semble qu'on est plutôt dans le défini par l'implémentation sauf si en fait on revient au type initial (càd que le pointeur casté provient lui-même d'un cast) auquel cas le comportement est garanti aux conditions d'alignement.

    Le code présenté n'est pas dans ce cas, le pointeur casté provenant d'un &.

    Essayer de représenter sans perte des entiers sur 64 bits dans des flottants sur 64 bits est voué à l'échec sur les plateformes IEE754. On est certain que certains entiers devront être codés comme NaN et même comme NaN signalant, avec un risque élévé d'effets indésirables dans les manipulations intermédiaires.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  18. #18
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Il me semble qu'on est plutôt dans le défini par l'implémentation sauf si en fait on revient au type initial (càd que le pointeur casté provient lui-même d'un cast) auquel cas le comportement est garanti aux conditions d'alignement.
    j'avais une chance sur deux. Je me susi tellement fait avoir que je paranoise

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Conversion float vers int
    Par jeremy75 dans le forum C++
    Réponses: 2
    Dernier message: 20/05/2014, 16h54
  2. Convertion char vers int
    Par barthelv dans le forum C
    Réponses: 8
    Dernier message: 08/10/2011, 21h45
  3. cast float vers int
    Par planeur2007 dans le forum C
    Réponses: 5
    Dernier message: 13/03/2007, 18h39
  4. Réponses: 12
    Dernier message: 31/12/2005, 16h01
  5. Conversion float vers int
    Par vargasvan dans le forum C
    Réponses: 2
    Dernier message: 05/10/2005, 17h29

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