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 :

Comment arrondir un flottant en perdant de la précision


Sujet :

C

  1. #1
    Candidat au Club
    Inscrit en
    Mai 2002
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Mai 2002
    Messages : 4
    Points : 4
    Points
    4
    Par défaut Comment arrondir un flottant en perdant de la précision
    Je suis en train de faire un petit programme de calcul mental.

    Je cherche comment faire pour arrondir un flottant en perdant sa précision de façon à ce que l'ordinateur trouve le même résultat que l'élève :

    0,2569879 + 0,25789654 = 0,51488444 pour l'ordinateur

    et

    0,25 + 0,25 =0,50 pour l'élève

    Je n'ai pas trouvé de telle fonction dans la libc.
    Je vous remercie d'aider le pauvre débutant que je suis.

  2. #2
    Membre régulier

    Inscrit en
    Décembre 2002
    Messages
    60
    Détails du profil
    Informations forums :
    Inscription : Décembre 2002
    Messages : 60
    Points : 105
    Points
    105
    Par défaut
    Un petit truc comme ca doit pouvoir fonctionner pour une precision de 2:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    float f = 0,2569879;
    float result = ((int) f * 100) / 100;
    La partie ((int) f * 100) donne 25, eliminant le reste des decimales. Rediviser par 100 redonne le resultat initial debarrasse de ses decimales.

    Au cas ou il reste des decimales en trop (a cause de la retransformation en float ou l'addition), il est possible d'imprimer avec une precision determinee:
    imprime f avec exactement deux decimales.
    Si la connaissance peut créer des problemes, ce n'est pas par l'ignorance que l'on peut les résoudre.
    -- Isaac Asimov

  3. #3
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par Elrond
    Un petit truc comme ca doit pouvoir fonctionner pour une precision de 2:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    float f = 0,2569879;
    float result = ((int) f * 100) / 100;
    La partie ((int) f * 100) donne 25, eliminant le reste des decimales. Rediviser par 100 redonne le resultat initial debarrasse de ses decimales.
    le probleme est que ((int)f*100) est un entier (sauf erreur de ma part) et qu'en contexte entier la division est entiere. Le resultat de la division est ensuite converti en float par l'affectation. Donc on aura 25/100=0 d'ou result=0.0. Il faut plutot faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    float result = ((float)((int) f * 100)) / 100;

  4. #4
    Membre régulier

    Inscrit en
    Décembre 2002
    Messages
    60
    Détails du profil
    Informations forums :
    Inscription : Décembre 2002
    Messages : 60
    Points : 105
    Points
    105
    Par défaut
    Exact. La philosophie y etait, mais il y avait effectivement un detail qui n'allait pas.

    Merci gl
    Si la connaissance peut créer des problemes, ce n'est pas par l'ignorance que l'on peut les résoudre.
    -- Isaac Asimov

  5. #5
    Membre émérite

    Homme Profil pro
    Urbaniste
    Inscrit en
    Mars 2002
    Messages
    255
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Aveyron (Midi Pyrénées)

    Informations professionnelles :
    Activité : Urbaniste

    Informations forums :
    Inscription : Mars 2002
    Messages : 255
    Points : 2 717
    Points
    2 717
    Par défaut
    Plutôt qu'utiliser tout le temps "(int)... truc double ...", utilisez plutôt modf (découpe en partie entière et décimale) ou alors une belle fonction d'arrondi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    // Arrondit un nombre réel au nombre entier le plus proche
    Reel Arrondit (const Reel x)
    {
      if (0 <= x)
        return Floor(x +(Reel)0.5);
      else
        return Ceil(x -(Reel)0.5);
    }
    avec :
    Reel = double
    Floor = floor
    Ceil = ceil

    Ca évite les débordement sur les nombres réels ! (tenter de stocker 10^13 dans un int par exemple ...)

    Conseil : utiliser double plutôt que float, prend + de mémoire, mais est plus précis !!!

    @+ Haypo

  6. #6
    Candidat au Club
    Inscrit en
    Mai 2002
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Mai 2002
    Messages : 4
    Points : 4
    Points
    4
    Par défaut
    Merci pour votre aide. J'ai essayé le premier truc qui consiste a convertir le nombre en entier le multiplier par 100 et le diviser par 100. Le problème est le suivant : lorsqu'on converti un flottant en entier le compilateur (gcc) a logiquement tendance à zapper la partie décimale pour ne garder que la partie entière. On se retrouve donc avec un nombre,00000.

    Quand à la seconde méthode, je l'essaye sans plus tarder afin de vous tenir au courant.

  7. #7
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par haypo
    Plutôt qu'utiliser tout le temps "(int)... truc double ...", utilisez plutôt modf (découpe en partie entière et décimale) ou alors une belle fonction d'arrondi :
    L'inconvenient de floor et ceil, c'est qu'ils arrondissent a l'entier le plus proche, on ne peut pas specifier directement un nombre de decimales, il faut donc bricoler un truc un peu comme les cast suivit de multiplicatio/division.
    Je ne connaissais pas modf mais ca a l'air d'etre bien pratique pour realiser ce genre de chose. Existe-t-il une fonction qui fait l'inverse ?

    Citation Envoyé par marco
    Merci pour votre aide. J'ai essayé le premier truc qui consiste a convertir le nombre en entier le multiplier par 100 et le diviser par 100. Le problème est le suivant : lorsqu'on converti un flottant en entier le compilateur (gcc) a logiquement tendance à zapper la partie décimale pour ne garder que la partie entière. On se retrouve donc avec un nombre,00000.
    As tu rajouter la petite modif consistant a reconvertir en float avant la division ?

  8. #8
    Membre régulier

    Inscrit en
    Décembre 2002
    Messages
    60
    Détails du profil
    Informations forums :
    Inscription : Décembre 2002
    Messages : 60
    Points : 105
    Points
    105
    Par défaut
    Citation Envoyé par haypo
    Ca évite les débordement sur les nombres réels ! (tenter de stocker 10^13 dans un int par exemple ...)

    Conseil : utiliser double plutôt que float, prend + de mémoire, mais est plus précis !!!

    @+ Haypo
    C'est un risque. Maintenant, etant donne que c'est pour du calcul mental, il y a peu de chances d'atteindre des valeurs supperieurs a un entier. Mais il est vrai qu'il est sans doute preferable de tester avant.

    Quand a l'utilisation du double, une fois encore, puisque le but est de reduire fortement la partie decimale, il n'est probablement pas utile d'avoir une precision diabolique

    C'est a marco de voir.
    Si la connaissance peut créer des problemes, ce n'est pas par l'ignorance que l'on peut les résoudre.
    -- Isaac Asimov

  9. #9
    Candidat au Club
    Inscrit en
    Mai 2002
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Mai 2002
    Messages : 4
    Points : 4
    Points
    4
    Par défaut
    Après maintes essai, la première solution (changement de type de variable float en int puis division par 100) fonctionne.

    Quand à la seconde solution qui consiste à séparer la partie entière de la partie décimale ne me semble pas très appropriée. En effet, même si je parviens à isoler la partie décimale dans un entier, comment vais-je faire pour lui enlever sa précision. Cela risque de coûter bien des efforts pour aboutir au même résultat que la fonction précédente.

    De plus comme le fait très justement remarquer Elrond, la précision des nombres nécessaire pour mon programme n'est pas très importante.

    N.B: la précision des nombres de type flottant est très élevée. Cependant les arrondis effectués par le processeur lors de l'exécution du code induisent une imprécision (je ne me rappelle plus de la formule qui permet de la calculer).
    par ex si on écrit float nombre=0.12;
    on risque de se retrouver avec printf("%f",nombre); qui renvoie 0.120000012200

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

Discussions similaires

  1. Comment arrondir un nombre?
    Par Dub's dans le forum C
    Réponses: 4
    Dernier message: 12/03/2007, 19h25
  2. [VB.Net] Comment arrondir un timestamp ?
    Par NicoNGRI dans le forum VB.NET
    Réponses: 1
    Dernier message: 07/02/2006, 17h16
  3. Comment arrondir à l'entier supérieur ?
    Par kuranes dans le forum Access
    Réponses: 3
    Dernier message: 29/11/2005, 17h42
  4. Comment arrondir une division à l'excès ?
    Par titiyo dans le forum Langage
    Réponses: 5
    Dernier message: 15/11/2005, 13h35
  5. [CR] Comment arrondir un chiffre a 3 ap la virgule en code
    Par speed034 dans le forum SAP Crystal Reports
    Réponses: 5
    Dernier message: 10/06/2004, 18h59

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