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 :

C++ math : abs(x) ou (unsigned)x ?


Sujet :

C++

  1. #1
    Membre éclairé Avatar de ttone
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    589
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2008
    Messages : 589
    Par défaut C++ math : abs(x) ou (unsigned)x ?
    abs(float) est une fonciton c++ qui apparemment n'appartient même pas à la lib standard (min, max...) . Mais c'est un détail.

    Suite à une remarque, je me demandais si le calcul abs :

    1 . n'était pas trop lourd ?
    2 . se contentait d'annuler le bit de signe ?
    3 . et donc s'il était équivalenbt (en opération, mais surtout en temps de calcul) à une conversion int-->uint (ou unsigned int) ?


    Merci!

  2. #2
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    abs fait bien plus que d'annuler le bit de signe...

    A vrai dire, ce qu'elle va faire va essentiellement dépendre de l'architecture sur laquelle tu travailles.

    En effet, il existe entre autre des architectures qui travaillent en "complément à deux" pour les nombres négatifs.

    Cela signifie que, alors que 0x0001 correspondrait à 1, ce qui correspond à -1 est... 0xFFFF (en hexadécimal et par exemple)

    Pour d'autres architectures, il est possible d'envisager que 0x0001 corresponde toujours à 1 mais que moins un corresponde à 0x8001 ou à ... va savoir quoi.

    De plus, il existe des architectures sur lesquelles la valeur maximale admise pour un entier non signé correspond à (la valeur maximale admise pour un entier signé) *2 - 1.

    Tout cela fait que si tu te contente d'annuler le bit de signe (et pour autant que tu aie la certitude de l'avoir effectivement repéré), tu risques très fortement de produire quelque chose qui ne soit absolument pas portable, et très dépendant de l'architecture ou de l'implémentation.
    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

  3. #3
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 967
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 967
    Par défaut
    Jai,
    Citation Envoyé par koala01 Voir le message
    Salut,

    abs fait bien plus que d'annuler le bit de signe...

    A vrai dire, ce qu'elle va faire va essentiellement dépendre de l'architecture sur laquelle tu travailles.

    En effet, il existe entre autre des architectures qui travaillent en "complément à deux" pour les nombres négatifs.

    Cela signifie que, alors que 0x0001 correspondrait à 1, ce qui correspond à -1 est... 0xFFFF (en hexadécimal et par exemple)

    Pour d'autres architectures, il est possible d'envisager que 0x0001 corresponde toujours à 1 mais que moins un corresponde à 0x8001 ou à ... va savoir quoi.

    De plus, il existe des architectures sur lesquelles la valeur maximale admise pour un entier non signé correspond à (la valeur maximale admise pour un entier signé) *2 - 1.

    Tout cela fait que si tu te contente d'annuler le bit de signe (et pour autant que tu aie la certitude de l'avoir effectivement repéré), tu risques très fortement de produire quelque chose qui ne soit absolument pas portable, et très dépendant de l'architecture ou de l'implémentation.
    Il est question de abs(float), et les considérations liées aux entiers signes ou non n'a pas lieu d'être.

    Cette réponse concerne également ttone : ne pas comparer les fonctions sur les flottants et sur les entiers, ça n'a pas vraiment de sens.

    En l'occurrence, ça peut dépendre du compilateur, et il faudrait aller voir le code généré, mais je parierais volontiers sur une simple mise à jour du bit de signe, puisqu'il est possible de se contenter de ça.

  4. #4
    Alp
    Alp est déconnecté
    Expert confirmé

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    Si, abs appartient à la bibliothèque standard... Tu as d'ailleurs normalement à mettre "std::" devant abs lorsque tu l'appelles.
    Elle est probablement dans <cmath>.

  5. #5
    Membre éclairé Avatar de ttone
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    589
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2008
    Messages : 589
    Par défaut
    Si, abs appartient à la bibliothèque standard... Tu as d'ailleurs normalement à mettre "std::" devant abs lorsque tu l'appelles.
    Elle est probablement dans <cmath>.
    oui et bien justement non, à ma grande surprise, je n'utilise pas "using namespace std" et pourtant je code comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    std::min(...);
    std::max(...);
    abs(...);
    std::abs m'est même refusé, à moins que ca ne soit mon API (Juce) qui ait son "abs" à elle chose dont je doute.

    Abs(float) ou abs(int) ?
    En fait j'utilise les deux, mais ma question concerne clairement les entiers...
    Ca concerne en fait de l'affichage 2D basique, que j'espère bien optimiser au maximum avant d'envisager d'autres outils (OpenGL) bien que je n'utilise que des translation. Les zooms sont à venir alors...

    Mais peut importe l'outil pour le moment, quand je vois des abs (yf-ti ) dans mon code, j'ai un sentiment de malaise ...

    Est ce que faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int x=-2
    unsigned int y=x;
    ne serait pas suffisant au fond ? Et au moins là je suis sûr de l'efficacité de la chose.

  6. #6
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 967
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 967
    Par défaut
    Hai,
    Citation Envoyé par ttone Voir le message
    Abs(float) ou abs(int) ?
    En fait j'utilise les deux, mais ma question concerne clairement les entiers...
    Pas si clairement que ça, puisque dans ton premier post
    Citation Envoyé par ttone Voir le message
    abs(float) est une fonciton c++ qui apparemment n'appartient même pas à la lib standard (min, max...)
    abs(float) est la seule version que tu cites, et en début de message, ce qui attire évidemment l'attention.

  7. #7
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par ttone Voir le message
    Est ce que faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int x=-2
    unsigned int y=x;
    ne serait pas suffisant au fond ? Et au moins là je suis sûr de l'efficacité de la chose.
    Justement, si tu essaye, tu risque d'avoir une belle surprise...

    Chez moi, par exemple, avec le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #include <iostream>
    using namespace std;
    int main()
    {
        int i = -2;
        unsigned int j = i;
        cout<<j<<endl;
        return 0;
    }
    j'obtiens... 4294967294...

    Ce qui est le exemple type de ce que j'expliquais plus haut, -2 étant représenté, chez moi, sous la forme hexadécimale, par 0xFFFFFFFE...
    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

  8. #8
    Membre éclairé Avatar de ttone
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    589
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2008
    Messages : 589
    Par défaut
    abs(float) est la seule version que tu cites, et en début de message, ce qui attire évidemment l'attention.
    Ok, au temps pour moi, pardon.
    C'est en fait une erreur d'ampleur : je pensais, en mettant float, élargir le débat, et non pas le déplacer...

    >>koala01 : merci, ca me rassure, le codage sur bits ne m'est pas si obscur par hasard...

    Donc pour résumer, pas moyen de se passer de abs(int) ? Et globalement, faut il le craindre plus qu'autre chose en termes de perf ?

    Merci!

  9. #9
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Honnêtement, il y a bien d'autres endroits où les performances seront directement atteintes si tu utilise, par exemple, de mauvais algorithmes...

    Dés lors, avant de t'intéresser à l'impact que peut avoir UNE instruction particulière, il est bien plus intéressant de veiller à fournir des algorithmes qui tiennent la route, et qui ne recourent par exemple pas à une boucle imbriquée (très grosse consommatrice en terme de performances) quand une approche dichotomique ou quand une boucle simple fait l'affaire.

    Il faut bien te dire que, au pire, ce que tu peux perdre en utilisant abs() au lieu d'une méthode plus "barbare" (principalement parce que moins lisible) va se compter en terme de cycles d'horloge processeur (un ou deux, à peine plus), et que je dois sans doute être le dernier de ma race à tourner sur un antique Athlon 1700 XP.

    Avec des processeurs dont les fréquences d'horloge flirtent allègrement avec le 3Ghz, crois moi, il faudrait déjà appeler très souvent (de l'ordre de 3.000.000 de fois) l'instruction sur une seule seconde avant de commencer effectivement à remarquer une infime perte de performances...
    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

  10. #10
    Membre Expert
    Avatar de SpiceGuid
    Homme Profil pro
    Inscrit en
    Juin 2007
    Messages
    1 704
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2007
    Messages : 1 704
    Par défaut
    Citation Envoyé par koala01
    En effet, il existe entre autre des architectures qui travaillent en "complément à deux" pour les nombres négatifs.
    Des architectures comme ia32, amd64, 680x0, PowerPC...
    Mais, en théorie, il n'est pas impossible que tu trouves un cpu sur lequel la conversion intuint donne le même résultat que abs.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    C'est justement la raison pour laquelle il ne faut pas partir de la moindre présomption quant à la manière dont les nombres signés et non signés seront représentés.

    En outre, vérification faite, abs est effectivement sensée fonctionner avec des réels (double ou float).

    Au final, la solution vraisemblablement la plus portable avec une efficacité suffisante sera, tout simplement un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int i = -2; /* la valeur à rendre positive
    /* unsigned  */ int positif = (i<0? i*(-1) : i);
    Nous ne pouvons à l'extrème limite même pas considérer qu'un int fait 32 bits, car il n'y a aucune obligation que ce soit le cas, et un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    /* unsigned */ int positif = ( i&0x80000000 /*...*/)
    serait par trop architecture / implémentation dépendant.
    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

  12. #12
    Expert confirmé

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Billets dans le blog
    3
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Nous ne pouvons à l'extrème limite même pas considérer qu'un int fait 32 bits, car il n'y a aucune obligation que ce soit le cas
    Et ce n'est pas le cas (en tout cas chez moi ! ).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    /* unsigned */ int positif = ( i&0x80000000 /*...*/)
    serait par trop architecture / implémentation dépendant.
    Et surtout est *exactement* ce que fait le compilateur
    Mais, question lisibilité .....

  13. #13
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Ben, là, il y a une contradiction...

    Si tes entiers ne font pas 32 bits, ton compilateur ne fera jamais une comparaison avec i&0x80000000 pour déterminer si un nombre est négatif
    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

  14. #14
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 967
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 967
    Par défaut
    Hai,
    Citation Envoyé par nicroman Voir le message
    Et surtout est *exactement* ce que fait le compilateur
    Mais, question lisibilité .....
    Ça dépend du compilateur, des optimisations demandées, ...

    Car on peut parfaitement faire appel à de petites astuces qui évitent de faire des tests/sauts, chers en temps d'exécution, astuces variant d'un processeur à l'autre, car évidemment directement dépendantes du jeu d'instructions.

  15. #15
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par SpiceGuid Voir le message
    Mais, en théorie, il n'est pas impossible que tu trouves un cpu sur lequel la conversion intuint donne le même résultat que abs.
    Une implementation non conforme alors (cette conversion doit etre modulo UINT_MAX+1)

  16. #16
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Par défaut
    Vous êtes sûr que abs dispose d'une surcharge pour les float ? En tout cas pas à en juger ce site.

    Pour les float j'ai toujours utilisé std::fabs.

  17. #17
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par Bakura Voir le message
    Vous êtes sûr que abs dispose d'une surcharge pour les float ?
    Oui, dans <cmath>. Les surcharges pour int et long sont dans <cstdlib>. La surcharge pour complex<T> dans <complex>, celle pour valarray<T> dans <valarray>.

  18. #18
    Rédacteur
    Avatar de Bakura
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2005
    Messages
    1 386
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 386
    Par défaut
    D'accord, j'apprends un truc alors . Et fabs ?

    PS : valarray, c'est pas standard ça non ?

  19. #19
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par Bakura Voir le message
    D'accord, j'apprends un truc alors . Et fabs ?
    Dans <cmath>

    PS : valarray, c'est pas standard ça non ?
    Si, 26.3 (26.5 dans N2800).

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

Discussions similaires

  1. [Débutant] Math.Abs(f).ToString() et exposent
    Par shaun_the_sheep dans le forum C#
    Réponses: 2
    Dernier message: 24/03/2015, 08h23
  2. [MATH] Point par rapport à une droite
    Par teska dans le forum Mathématiques
    Réponses: 6
    Dernier message: 14/05/2003, 16h11
  3. #include "math.h" et #include <math.h>
    Par pounka dans le forum C
    Réponses: 4
    Dernier message: 01/05/2003, 21h06
  4. Problème de math....
    Par zdra dans le forum Mathématiques
    Réponses: 6
    Dernier message: 11/11/2002, 10h59
  5. Maths : équations
    Par Anonymous dans le forum Mathématiques
    Réponses: 5
    Dernier message: 02/05/2002, 16h41

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