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

Python Discussion :

Trouver puissance de deux supérieure la plus proche. [Python 3.X]


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Mars 2008
    Messages
    104
    Détails du profil
    Informations forums :
    Inscription : Mars 2008
    Messages : 104
    Par défaut Trouver puissance de deux supérieure la plus proche.
    Bonjour,

    Je cherche donc à trouver la puissance de deux la plus proche d'une nombre et supérieure à celui-ci. Cependant, je voudrais quelque chose de plus raffiné qu'une boucle while avec une série de test. J'ai donc cherché un peu et ai trouvé cet article parlant du sujet :
    https://grim7reaper.rolinh.ch/blog/2...e-a-un-nombre/
    Cependant, j'ai du mal à comprendre son code et donc à le transposer en Python. Quelqu'un y verrait-il plus clair dans ce qui est écrit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    unsigned next_highest_power_of_2(unsigned n)
    {
        unsigned i;
        --n;
        for(i = 1; i < sizeof n * CHAR_BIT; i <<= 1)
            n |= n >> i;
        return ++n;
    }

  2. #2
    Expert confirmé Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 041
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 041
    Par défaut
    salut,

    si l'auteur passait dans le coin il te l'expliquerait sûrement, ce que je retiens perso de son article c'est qu’il n’y a pas de pire cas (sic). en fait et sauf erreur, il fait très exactement ce que tu ne veux pas faire, à savoir une boucle de 1 à n

    sinon une méthode parmi d'autres pour faire ça en python pourrait être :
    c'est moche, et ça marche du tonnerre, sans boucle apparente ;p

  3. #3
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 754
    Par défaut
    Salut,

    Sans boucle apparente...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    >>> from math import ceil, log, pow
    >>> next = lambda x: int( pow(2, ceil(log(x, 2))))
    >>> next(20)
    32
    >>>
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  4. #4
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Encore plus simple (si Python version >=3.1):

    [edit]: et si on éviter le calcul d'une puissance:


  5. #5
    Membre confirmé
    Inscrit en
    Mars 2008
    Messages
    104
    Détails du profil
    Informations forums :
    Inscription : Mars 2008
    Messages : 104
    Par défaut
    Merci pour toutes vos réponses.

    Citation Envoyé par BufferBob Voir le message
    salut,

    si l'auteur passait dans le coin il te l'expliquerait sûrement, ce que je retiens perso de son article c'est qu’il n’y a pas de pire cas (sic). en fait et sauf erreur, il fait très exactement ce que tu ne veux pas faire, à savoir une boucle de 1 à n
    De ce que je comprends, il fait cette boucle dans la section 1 Approche naïve mais dans la section 2 Optimisation cela semble différent.

    Du coup, j'en étais arrivé au petit bout de code suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    x = 1024
     
    # Calculate number of bits
     
    nb_bits = x.bit_length()
     
    # Calculate number of bits
     
    x_new = 2 ** (nb_bits)
    Mais suite au message de tyrtamos, il y a en effet bien plus simple.

    Cela fonctionne très bien sauf si x est égal à une puissance de 2. Dans ce cas, cela prend la puissance de 2 supérieure. Par exemple, si x = 1024, cela fait 11 bits et 2**11 fait 2048. Mais je peux régler cela avec une condition :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if x == 2 ** (nb_bits-1):
        x_new = x
    else:
        x_new = 1<<(x).bit_length()
    Voyez-vous une méthode plus simple/rapide que cette condition ?

    J'aurais cependant deux questions. Premièrement par rapport à ce message :

    Citation Envoyé par tyrtamos Voir le message
    [edit]: et si on éviter le calcul d'une puissance:

    Donc cela fonctionne mais j'ai du mal à comprendre exactement ce que cette fonction teste. Par exemple, [/QUOTE] me renvoi 0 mais je ne comprends pas pourquoi...

    Pour finir, quelle est la différence entre :

    et :

    Est-ce juste une différence Python 2.x et Python 3.x où il y a-t-il d'autres subtilités ?

  6. #6
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 754
    Par défaut
    Citation Envoyé par elglantosimpatico Voir le message
    Cela fonctionne très bien sauf si x est égal à une puissance de 2. Dans ce cas, cela prend la puissance de 2 supérieure. Par exemple, si x = 1024, cela fait 11 bits et 2**11 fait 2048. Mais je peux régler cela avec une condition :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if x == 2 ** (nb_bits-1):
        x_new = x
    else:
        x_new = 1<<(x).bit_length()
    Voyez-vous une méthode plus simple/rapide que cette condition ?


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1 << (x-1).bit_length()
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  7. #7
    Expert confirmé Avatar de BufferBob
    Profil pro
    responsable R&D vidage de truites
    Inscrit en
    Novembre 2010
    Messages
    3 041
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : responsable R&D vidage de truites

    Informations forums :
    Inscription : Novembre 2010
    Messages : 3 041
    Par défaut
    Citation Envoyé par elglantosimpatico Voir le message
    De ce que je comprends, il fait cette boucle dans la section 1 Approche naïve mais dans la section 2 Optimisation cela semble différent.
    c'est pareil, la version optimisée contient une boucle également, il la déplie même plus bas dans son article
    outre la méthode employée (dans la naïve on compare n avec une puissance de 2 jusqu'à ce que ça dépasse, dans l'optimisée on met tous les bits à 1 et à la fin on incrémente pour avoir la puissance de 2 supérieure), la différence entre les deux tient dans le fait que pour une taille d'entier donné, mettons 16bits, où n=16362, la fonction naïve fera tourner sa boucle 14 fois (jusqu'à tomber sur 16384 > n) tandis que la fonction optimisée fera tourner la sienne 4 fois et ce quelque soit la valeur de n codée sur 16bits

    la boucle de la fonction optimisée est pourtant très visible (mais pas forcément très lisible) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for (i = 1; i < sizeof(n) * CHAR_BITS; i <<= 1)
    si on a un nombre n sur 64 bits par exemple, la variable i dans la boucle prendra successivement les valeurs 1,2,4,8,16 et 32, dernière valeur à ne pas passer la condition d'arrêt de la boucle, donc 6 itérations seulement

    l'opérateur << effectue un décalage de x bits vers la gauche, donc si on prend le nombre 1, qu'on codera au minimum dans un type C char (8 bits) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    1      == 00000001
    1 << 6 == 00000001 << 6
    1 << 6 == 01000000
    1 << 6 == 64
    idem pour l'opérateur >> qui effectuera un décalage de bits vers la droite

    or décaler de x bits vers la gauche ou la droite revient ni plus ni moins à multiplier ou diviser x fois par 2, ça revient donc au même que 2x, qu'à l'occasion on écrit 2**x en python (ou à l'inverse 2**(1/x) donc), mais les deux écritures reviennent en pratique à la même chose

    quant à bin(n)[2:] c'est juste très moche, puisque ça implique une conversion du nombre pour ensuite lui amputer deux caractères, bref c'est pas joli, mais ça marche
    ceci dit et même si utiliser n.bit_length() est bien plus élégant, rien ne garantit qu'il n'y a là dedans aucune boucle non plus (je suis près à parier que si)

    enfin il faut comprendre que chercher des méthodes optimisées au cycle ou au bit près pour écrire la routine en Python n'a pas vraiment de sens, ça a un sens avec un programme C ou C++ parcequ'on a un contrôle très fin sur le code machine généré et on sait qu' hormis quelques bidouilles salvatrices du compilateur ce qu'on a dans le code source se retrouvera dans le code machine, alors qu'en Python ça n'est pas le cas, par exemple là où n |= n >> i; donnera ~5 instructions une fois compilé, l'équivalent en Python peut très bien occasionner l'exécution de +100 instructions, ce qui fera perdre tout son sens à l'optimisation en question

  8. #8
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 754
    Par défaut
    Citation Envoyé par elglantosimpatico Voir le message
    Est-ce juste une différence Python 2.x et Python 3.x où il y a-t-il d'autres subtilités ?
    Pour ce genre de question il faut prendre le temps d'aller lire la documentation.
    Vous y trouverez les 2 autres méthodes mentionnées ici comme alternatives à... et qu'il n'y a pas de changement côté Python3.

    Citation Envoyé par BufferBob Voir le message
    quant à bin(n)[2:] c'est juste très moche, puisque ça implique une conversion du nombre pour ensuite lui amputer deux caractères, bref c'est pas joli, mais ça marche
    ceci dit et même si utiliser n.bit_length() est bien plus élégant, rien ne garantit qu'il n'y a là dedans aucune boucle non plus (je suis près à parier que si)
    Oui çà boucle mais, le code est écrit en C.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  9. #9
    Membre confirmé
    Inscrit en
    Mars 2008
    Messages
    104
    Détails du profil
    Informations forums :
    Inscription : Mars 2008
    Messages : 104
    Par défaut
    Merci beaucoup pour votre aide.

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

Discussions similaires

  1. Réponses: 6
    Dernier message: 11/11/2015, 13h38
  2. Réponses: 4
    Dernier message: 04/03/2010, 21h35
  3. algorithme des deux points les plus proches
    Par biba1980 dans le forum Algorithmes et structures de données
    Réponses: 8
    Dernier message: 10/11/2009, 04h18
  4. Puissance entière de 2 la plus proche
    Par Razgriz dans le forum Mathématiques
    Réponses: 16
    Dernier message: 30/10/2007, 12h17
  5. Puissance de deux supérieure
    Par NiamorH dans le forum C
    Réponses: 30
    Dernier message: 02/04/2007, 10h29

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