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 :

Inverse d'un nombre décimal,


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    105
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 105
    Par défaut Inverse d'un nombre décimal,
    Bonsoir,

    Je me retrouve face à un problème "tout bête" que je ne sais pas résoudre...
    Comment prendre l'inverse d'un nombre décimal tel que 0.1, 0.001, 0.001... sous forme d'un int ?
    J'ai réussi à écrire en C le calcul approché de l'intégrale de 0 à 1 de 4/(1+x²) grâce à la formule de Simpson composée qui me donne une approximation de Pi.
    Je donne pour le moment la largeur du pas p (je veux laisser ce choix ultérieurement à l'utilisateur) : p =0.001 (par exemple) qui va me donner 1000 comme terme de la boucle de calcul.
    Le programme fonctionne avec déclaration de float p =0.001; et int nb=1000;
    mais si je m'avise d'écrire int nb; puis nb = floor(1/p) je déclenche une erreur à la compilation : warning : try to convert double to int...
    J'ai fini, difficilement, par comprendre pourquoi...
    Par contre, je ne sais pas comment contourner le problème : p=0.001, son inverse est 1000, nombre entier... Le problème vient du floor qui renvoie un double...
    Y a-t-il moyen de convertir un décimal (double ou float) dont on sait que sa partie décimale est nulle (c'est le cas de 1/p) en un nombre entier ?
    Je vous remercie par avance de votre indulgence.
    Et je remercie, dans la foulée, tout familier du C qui viendra me tirer du marais où je me suis enlisé.

    Cordialement,

    @+

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 483
    Par défaut
    Bonjour,

    Tu peux tout-à-fait convertir un type numérique en un autre. Si le type-cible est moins précis que le type source, alors la valeur sera tronquée mais convertie quand même. Ici, convertir un flottant en entier est le meilleur moyen de se débarrasser de sa partie décimale.

    Il s'agit d'un warning, ce qui veut dire dans le cas présent que ton compilateur te prévient qu'il va faire implicitement et de lui-même une conversion. Si c'est bien ce que tu veux faire, tu peux transtyper (cast) ton nombre toi-même.

    Donc, dans le cas qui t'intéresse :

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        int     x;
        float   y;
     
        y = 0.0001;
        x = (int)(1.0/y);

    Le tout est de s'assurer que l'on fait bien le calcul de l'inverse en float et que, seulement ensuite, on tronque le résultat uniquement, en le transtypant en entier. « 1.0 » plutôt que « 1 » sert à indiquer que le numérateur est flottant lui-aussi, sinon le compilo risque de convertir y en entier avant de faire le calcul.

  3. #3
    Membre éprouvé

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 116
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 116
    Par défaut
    si tu fais une intégration, tu n'es pas obligé de calculer le nombre de pas. Une simple boucle while peut suffire (c'est d'ailleurs plus propre que de calculer un nombre de pas de cette manière)

    Concernant le transtypage proposé plus haut, je te conseille plutôt la chose suivante : transtype en entier le résultat de la fonction floor. Je ne sais pas si la troncature est explicite, mais dans le doute, mieux vaut préciser si c'est un arrondi ou une troncature que tu fais.

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    105
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 105
    Par défaut
    Bonsoir,

    Décidément, quelle réactivité !!!
    Bon, le while m'oblige à gérer un compteur indépendant, alors qu'il est intégré dans le for...
    Je ne vois pas pourquoi le for est moins "propre" que le while ? J'essaierai ton truc (que je comprenne d'abord ce que ça veut dire et comment le faire), mais pas ce soir...
    En tous cas la solution de obsidian lève l'erreur.
    Pour mieux comprendre ce que j'ai raconté, voilà mon code :
    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
    22
    23
    24
    25
    26
    27
    # include <stdio.h>
    # include <stdlib.h>
    # include <math.h>
     
    int main()
    {
        double s;
        double p = 0.001;
        double pi =M_PI;
        int a = 0,b = 1,k,nb;
        s=0;
        nb=(int)(1.0/p);
        printf("          Valeur Approchée de Pi\n\n");
        printf("Par approximation de l'intégrale de 0 à 1 de 4/(1+x^2)\n");
        printf("          Méthode de Simpson composée\n\n\n");
     
        for(k=1;k<nb;k++)
        {
         s+=(1+k%2)*4/(1+pow(a+k*p,2));
        }
        s=p/3*(4/(1+pow(a,2))+4/(1+pow(b,2))+2*s);
     
        printf("Valeur  connue de Pi = %.18f\n",pi);
        printf("Valeur obtenue de Pi = %.18f\n\n",s);
        system("pause");
        return 0;
    }
    Au passage, je constate que, question lettres accentuées, C est aussi "drôle" que Python...
    Bon, résultat exact à 0.1 près... bof ! bof !
    Parce que avant d'utiliser nb = (int)(1.0 / p); quand j'écrivais nb = 1000; j'obtenais un résultat exact à 10^-15 près...
    Hallucinant !!!
    Donc c'est le nb=(int)(1.0/p); qui ne donne pas le résultat escompté...
    Qui peut expliquer ça ?

    Merci d'avance

    @+

  5. #5
    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 : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par Obsidian Voir le message
    Le tout est de s'assurer que l'on fait bien le calcul de l'inverse en float et que, seulement ensuite, on tronque le résultat uniquement, en le transtypant en entier. « 1.0 » plutôt que « 1 » sert à indiquer que le numérateur est flottant lui-aussi, sinon le compilo risque de convertir y en entier avant de faire le calcul.
    L'utilisation de 1.0 n'est pas indispensable ici, la division n'est entière que si les deux opérandes sont entières. Si au moins une des deux est réelle (ce qui est le cas puisque y est un float), la division est réelle (1 est converti en float, pas y en int).

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    105
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 105
    Par défaut
    Bonjour,

    @gl ok ça éclaircit un certain nombre de choses.

    Bon, pour faire avancer mon problème, après nb = (int)(1/p);
    J'ai ajouté la ligne printf("%3d",nb);
    Et le résultat est 999 et non 1000... D'où ma valeur de Pi calculée à 3,13...
    Et tout le problème est là : la formule de Simpson utilisée demande un nombre d'intervalles pair, donc de tours de boucle pair...
    Là, il y a vraiment un problème de conversion, voire de représentation des nombres à virgule...

    Bon je pourrais tricher et modifier le For ainsi :
    For (k=0; k<nb+1;k++);
    ou
    nb = (int) (1/p)+1
    Mais ce n'est pas intellectuellement satisfaisant...
    Je viens aussi d'essayer
    double nb;
    nb=floor(1/p);
    printf("%4d",nb);
    Le résultat, là est 0...
    Affreux...

    Ma question est donc : comment faire pour que C me donne 1000 comme inverse de 0.001 ?
    Transformer 0.001 en 10^-3, récupérer l'exposant, changer son signe et écrire nb = 10^3 ?
    Ca ferait assez : je prends un bazooka pour détruire un moustique...

    Non, il doit bien y avoir un moyen direct rapide dans le langage C si réputé, au point que certains modules additionnels en Python sont écrits en... C.

    Quelqu'un connaît-il le moyen de faire sauter l'obstacle ? Dans ce cas, je le remercie par avance de prendre un peu de temps pour m'en faire part...

    @+

  7. #7
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 104
    Par défaut
    J'ai ajouté la ligne printf("%3d",nb);
    Et le résultat est 999 et non 1000...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    double p = 0.001 ;
    int nb ;
    nb = (int) ( 1.0 / p ) ;
    printf ( "%3d" , nb ) ;
    m'affiche bien 1000

    Je viens aussi d'essayer
    double nb;
    nb=floor(1/p);
    printf("%4d",nb);
    Le résultat, là est 0...
    Affreux...
    1000 chez moi.
    (As-tu bien lié la librairie mathématique ?)

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    105
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2008
    Messages : 105
    Par défaut
    RE,

    Merci.
    J'ai recréé un programme de test en copiant/collant le morceau suggéré en exemple1 :
    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
    # include <stdio.h>
    # include <stdlib.h>
    # include <math.h>
     
    int main()
    {
        double p = 0.001 ;
        double np;
        int nb ;
        np=floor(1/p);
        nb = (int) ( 1.0 / p ) ;
        printf("np = %3d\n",np);
        printf ("nb = %3d\n\n" , nb ) ;
        system("pause");
        return 0;
    }
    Résultat


    Qu'est-ce qui ne va pas ?
    Ne serait pas suffisant d'écrire le # include <math.h> ?

    @+

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

Discussions similaires

  1. Réponses: 4
    Dernier message: 21/12/2005, 12h20
  2. [VB.NET] Nombre décimal
    Par Sadneth dans le forum ASP.NET
    Réponses: 8
    Dernier message: 25/11/2005, 12h41
  3. insérer un nombre décimale dans une table
    Par mouloudéen dans le forum Access
    Réponses: 4
    Dernier message: 02/10/2005, 21h29
  4. CRITERIA - Représentation binaire d'un nombre décimal signé.
    Par RamDevTeam dans le forum Décisions SGBD
    Réponses: 1
    Dernier message: 10/08/2005, 14h56
  5. [VB6]fonction inverse de Hex (nombres hexadécimaux)
    Par Guigui_ dans le forum VB 6 et antérieur
    Réponses: 4
    Dernier message: 08/10/2002, 19h31

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