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 :

Fonction divisant argument de type inconnu


Sujet :

C

  1. #1
    Membre éprouvé
    Profil pro
    Eleveur de cornichons
    Inscrit en
    Juin 2002
    Messages
    1 074
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Eleveur de cornichons
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 074
    Points : 1 166
    Points
    1 166
    Par défaut Fonction divisant argument de type inconnu
    Bonjour

    J'ai quelques petit soucis technique à cause de ma médiocre connaissance des fonctions C.
    Voila, je voudrais faire une fonction qui va me diviser l'argument par deux (j'ai simplifier l'action de cette fonction, en fait elle va faire plus que diviser) l'argument qui lui est transmis. Facile...
    Le problème : je ne connais pas le type de l'argument de la fonction, mais c'est numérique c'est sûr, donc ca peut etre int, float ou double.
    Là aussi c'est pas très dur puisque il suffit de faire une fonction ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     void add(void* x , char type)
    { switch(tolower(type))
     { case 'i' :
          *(int*)x /=2 ;
    break ;
    case 'l' :
    *(double*) x /=2 ;
    break ;
    case 'f' :
    *(float*)x /=2 ;
    break ;
     }
    }
    Seulement, cette fonction suppose que l'on connait le type transmi puisqu'on l'indique en seconde argument...
    Alors existe-t-il une méthode si l'on ne connait pas le type de l'argument, je voudrais une méthode portable si possible (Windows/Linux).

    Merci

    Nas'

  2. #2
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 15
    Points : 13
    Points
    13
    Par défaut
    Juste une question :
    Dans le cas où ton 1er argument est un int, tu fais comment si c'est un nombre impair ?

    Ce que je comprends pas, c'est pourquoi tu t'embêtes à faire autant de cas ...
    Il suffit que tu déclares ton premier argument en tant que double, et généralement la conversion automatique de int-> double et de float-> double se fait à chaque fois sauf cas exeptionnel (je crois que j'avais eu un problème avec la librairie OpenGL une fois qui ne voulait rien savoir sur cette histoire de conversion).

    Ta fonction serait beaucoup plus simple, car le 2ème argument deviendrai un peu inutile, et tu peux être sur que ce sera portable.

    @+
    Watchi

  3. #3
    Membre averti
    Avatar de joellel
    Profil pro
    Inscrit en
    Février 2003
    Messages
    234
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Février 2003
    Messages : 234
    Points : 338
    Points
    338
    Par défaut
    Attention! La méthode de Watchi marche, mais elle n'est pas trop rigoureuse (laisse trop la machine faire ce qu'elle veut pour les arrondis et troncatures).
    Je crois Nasky que c'est l'occasion de regarder un peu le C++
    Tu as un truc super qui s'appelle la surcharge de fonctions. Tu codes 3 fonctions de même nom, par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    void divise (int * arg) {
    *arg/=2;
    }
    void divise (float* arg) {
    *arg/=2.0;
    }
    void divise (double* arg) {
    *arg/=2.0;
    }
    Et en fonction du type de paramètre passé lors de l'appel, le compilateur décide lui même quelle fonction appeler...
    C'est pas génial ça???? Et ce n'est pas encore de l'objet, c'est juste une extension du C...

  4. #4
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 15
    Points : 13
    Points
    13
    Par défaut
    Ben disons que ça dépends ce que tu désires obtenir ... le problème se situant au niveau des int ...
    si i = 3, j = i/2 ... quel résultat attends-tu ? 1 (arrondi inférieur), 2 (arrondi supérieur) ou 1,5 (répose exacte)
    si c'est 1, en effet la méthode de joellel est la mieux (car plus simple, pas de modification à faire pour obtenir le nombre arrondi)
    si c'est 2, en effet la méthode de joellel est toujours la mieux (sauf qu'il faudrait faire quelques modification au programme) car plus "explicite"
    si c'est 1,5 ... ben les 2 premières méthodes ne le feront pas

    @joellel : justement ma méthode ne fait pas de troncature ou d'arrondis implicites (sous-entendus, que c'est la machine qui fais implicitement l'arrondis dans les cas de nombres impairs) pour les ints contrairement aux vôtres ... et je vois pas trop en quoi il y'aurait plus d'erreurs de ce type pour les floats et les doubles ...

    La conversion implicite est tout principalement dû à un problème de place ... un char fait 1 octet, un int en fait 2, float 4 et double 8 ...
    la différence entre les char/int et les float/double étant que dans les premiers c'est codé "direct" en binaire alors que dans les deuxièmes ça utilise une mantisse et un exposant ....

  5. #5
    Membre averti
    Avatar de joellel
    Profil pro
    Inscrit en
    Février 2003
    Messages
    234
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Février 2003
    Messages : 234
    Points : 338
    Points
    338
    Par défaut
    Comme tu l'avais dit (pour OpenGL), il y a des cas ou ca ne marche pas!!
    Et je crains plus les cas ou tu travailles sur un int et où tu fais le calcul sur un double, là tu peux avoir des problèmes de précision, par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    void divise(double *arg) {
    *arg/=2.0;
    }
    int main(void) {
    int i=4;
    divise(&i);
    printf("%d\n", i); 
    return 0;
    }
    Il m'est déjà arrivé dans ce cas de figure d'obtenir 1 au lieu de 2 car le calcul en virgule flottante n'étant pas exact, 4/2 peut donner 1,999999999999, donc, après conversion en entier par troncature, tu obtiens 4/2 = 1

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 15
    Points : 13
    Points
    13
    Par défaut
    ça m'étonnerait que dans le cas d'une division par 2 ça fasse ce genre de résultat ... tu pourras toujours essayer un bon paquet de fois mais soit ...
    (la raison étant que la division par 2 d'un entier donne un résultat fini....)

    En revanche, je suis d'accord avec toi que pour des divisions rendant des résultats non finis, donc approchés (par exemple une division par 3 ou 7), ma méthode est dangereuse car elle peut donner le type de cas de figure dont tu parles

    Mais bon je reste quasi persuadé (je dirais 95%) que 4/2 ne donnera pas 1,999999999999 mais bien 2.00000000 (avec autant de zéro que possible) de même 3/2 ne donnera pas 1,4999999999 mais bien 1,5000000

    Enfin, de toute façon c'est pas bien grave ... au moins comme ça Nasky tu auras eu plusieurs méthodes avec leurs avantages et leurs inconvénients.

  7. #7
    Membre averti
    Avatar de joellel
    Profil pro
    Inscrit en
    Février 2003
    Messages
    234
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Février 2003
    Messages : 234
    Points : 338
    Points
    338
    Par défaut
    Citation Envoyé par Watchi
    ça m'étonnerait que dans le cas d'une division par 2 ça fasse ce genre de résultat ... tu pourras toujours essayer un bon paquet de fois mais soit ...
    Ca m'est malheuresement déjà arrivé Je ne t'explique pas le temps de débogage!!!
    Enfin, de toute façon c'est pas bien grave ... au moins comme ça Nasky tu auras eu plusieurs méthodes avec leurs avantages et leurs inconvénients.
    Bon courage à lui

  8. #8
    Expert éminent sénior

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 750
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 750
    Points : 10 669
    Points
    10 669
    Billets dans le blog
    3
    Par défaut
    Pourquoi ta fonction de division s'appelle add ?
    Moi aussi je te conseille le C++ et la surcharge. Ton code est limite car void* c'est pas terrible, tout comme les cast sauvages.
    L'alternative à la surcharge en C c'est ca :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void diviseInt(int * arg) { 
    *arg/=2; 
    } 
    void diviseFloat(float* arg) { 
    *arg/=2.0; 
    } 
    void diviseDouble(double* arg) { 
    *arg/=2.0; 
    }
    Y'a aussi plus crade :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    #define divise( x ) *x /= 2;

  9. #9
    Membre éprouvé
    Profil pro
    Eleveur de cornichons
    Inscrit en
    Juin 2002
    Messages
    1 074
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Eleveur de cornichons
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 074
    Points : 1 166
    Points
    1 166
    Par défaut
    Salut
    Merci d'avoir répondu

    Ma fonction s'appelle Add dans l'exemple, je sais pas pourquoi en plus, c'est pour diviser ! Pas grave...
    Apparament la surcharge de fonctions semble être une méthode simple, je ne connaissais pas, c'est très pratique.
    Pour la méthode de Watchi, en fait, ma fonction ne divise pas par deux, et ne divise ... elle est un peu plus complexe mais c'est sur je n'aurais pas de problème de conversion, du moins je pense. Je vais traiter cela.
    La fonction recoit en fait les coordonnées d'un point et calcule de nombreux trucs par rapport à un point fixe défini dans la fonction ... mais ca n'a pas d'importance.
    Je vais donc opter pour la surcharge de fonctions.
    Merci bien

    Nas'

  10. #10
    Membre actif
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    304
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 304
    Points : 253
    Points
    253
    Par défaut
    Pour répondre a ta question, le meilleur moyen si tu fonctionnes en C , est de faire une surcharge des fonctions c'est a dire de déclarer toutes les fonctions dont tu as besoin (une pour chaque type).
    exemple:
    int div(int,int);
    int div(int,short);
    int div(int,long);
    ...

    Une petite information pour toi; si tu cherches a faire une division par 2, le meilleur moyen est de faire un décalage de bit ; autrement dit si tu veux diviser i par 2 tu fais
    i>>=1;
    Cette opération prends 2 cycles CPU contre 16 pour une division entiere!!!
    TOUT CE QUI EST VRAISEMBLABLE N'EST PAS FORCEMENT VRAI . MEFIEZ VOUS

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

Discussions similaires

  1. Fonction qui retourne un type inconnu (templates?)
    Par B65AcR dans le forum Débuter
    Réponses: 5
    Dernier message: 02/03/2014, 14h07
  2. argument de type objet d'une fonction
    Par bl4cksky dans le forum Débuter
    Réponses: 2
    Dernier message: 04/06/2013, 07h32
  3. Réponses: 14
    Dernier message: 18/07/2011, 21h00
  4. Réponses: 5
    Dernier message: 18/02/2009, 15h40
  5. [Fonction C] documentation & argument de type setof
    Par VASAPANCH dans le forum PostgreSQL
    Réponses: 0
    Dernier message: 11/07/2008, 12h14

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