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

Fortran Discussion :

Test pour détecter une puissance de 2


Sujet :

Fortran

  1. #1
    Membre régulier Avatar de moomba
    Profil pro
    Inscrit en
    avril 2007
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : avril 2007
    Messages : 134
    Points : 104
    Points
    104
    Par défaut Test pour détecter une puissance de 2
    Bonjour

    Je cherche à faire quelque chose de très simple :

    Soit la variable MonEntier (qui comme son nom l'indique est un entier).

    Comment savoir si c'est une puissance de 2 ?

    Je cherche à faire quelque chose sans boucles.

    J'ai pensé au fait qu'une puissance de 2 en binaire vaut toujours 1 puis que des zéros. (donc si on fait la somme de tout ses bits, on doit obtenir 1). Mais comment réaliser une telle opération en fortran ?

    Merci d'avance pour votre aide

    Moomba
    "Celui qui à le pouvoir de faire le mal, mais qui ne le fait pas, celui là est le prince de l'univers." (shakespeare)

  2. #2
    Membre éclairé Avatar de genteur slayer
    Homme Profil pro
    Développeur informatique
    Inscrit en
    juin 2002
    Messages
    710
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : juin 2002
    Messages : 710
    Points : 825
    Points
    825
    Par défaut
    tu as raison sur un point: quelque soit la taille en mémoire d'un entier, il est une puissance de deux si et seulement si il s'écrit avec un seul de ses bits à 1.
    cependant, en opération booléenne, 1+1+1=1en revanche un xor (ou exclusif) sur l'ensemble des bits peut te sauver
    mais il te faudra de toute façon faire une boucle (sur l'ensemble des bits de ton nombre).
    de plus il te faudra connaitre la taille de l'entier qui peux être assez variable en fonction de la volonté du programmeur et de l'architecture.
    de plus il faut que tu fasse attention aux entiers signés ou non... car dans ce cas, il y a un bit de signe, sa position peut dépendre de l'architecture...
    il n'y a que ceux qui savent qui ne savent pas qu'ils savent...
    Libere-toi hacker, GNU's Not Unix!!!

  3. #3
    Membre régulier Avatar de moomba
    Profil pro
    Inscrit en
    avril 2007
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : avril 2007
    Messages : 134
    Points : 104
    Points
    104
    Par défaut
    Merci pour ces précisions. (et désolé du retard )

    Comme je ne fait le test qu'au début du programme, j'ai finalement opté pour une boucle.

    Voici le programme, si ca peut un jours aider quelqu'un

    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
    28
    29
    30
    31
    program toto
     
    implicit none
     
    integer :: mavariable,test,n
     
    mavariable = 64 ! Variable à tester
     
    test = -1
     
    do n=1,1000
     
       if(mavariable == 2) then
          test=1
          exit
       end if
       if(mavariable < 2) then ! 1 ou 0, ou négatif
          test=0
          exit
       end if
     
       mavariable = mavariable/2
     
    end do
     
    if(test == -1) stop "Error"
     
    print *,"Test result :",test
     
     
    end program toto
    Voilà

    Merci beaucoup pour ton aide
    "Celui qui à le pouvoir de faire le mal, mais qui ne le fait pas, celui là est le prince de l'univers." (shakespeare)

  4. #4
    Membre éclairé Avatar de genteur slayer
    Homme Profil pro
    Développeur informatique
    Inscrit en
    juin 2002
    Messages
    710
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : juin 2002
    Messages : 710
    Points : 825
    Points
    825
    Par défaut
    ton programme est pas mal, cependant j'aurais quelques remarques:
    -faire la boucle jusqu'à 1000 est un peu abusif (même si tu as mis des exit) car au mieux tes entier sont 64bit (integer*8 ou integer(kind=8)) donc 2**64 c'est le max...
    -de plus en fortran, tous les integer sont signé et pour moi, -2**8 par exemple est une puissance de deux... et ' if(test == -1) stop "Error" ' serai alors vrai... (et du coup tes entier sont au mieux compris entre -2**32-1 et 2**32)
    en reprenant le principe que tu as utilisé (et mis dans une fonction)
    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
     
    function puissdeux(a)
      implicit none
      integer,intent(in) :: a
      integer puissdeux
    !
      integer b
    !
      puissdeux = 0
    !
      b=iabs(a) ! on peut aussi utiliser abs
      do while(b>1)
        if (mod(b,2)/=0) then
          puissdeux = -1
          exit
        else
          b=b/2
          puissdeux=puissdeux+1
        end if
      end do
    !
      return
    end function puissdeux
    sinon, je n'y avais pas pensé avant, mais pour faire sans boucle, il y a la fonction log2 (logarithme de base 2):

    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
     
    function puissdeux2(a)
      implicit none
      integer,intent(in) :: a
      integer puissdeux2
    !
      integer b
      real(kind=8) temp
    !
      b=iabs(a) ! on peut aussi utiliser abs
      temp=log(real(a))/log(2.)
      if ((real(int(temp))==temp).and.(temp>=0))then
        puissdeux2=int(temp)
      else
        puissdeux2=-1
      end if
    !
      return
    end function puissdeux2
    dans les deux cas, quelque soit le signe de a, la fonction revoie -1 si ce n'est pas une puissance de deux sinon, elle renvoie la valeur de la puissance

    j'ai eu en sortie:
    a puissdeux(a) puissdeux2(a)
    8 3 3
    7 -1 -1
    78 -1 -1
    -1024 10 10

    voilà!
    il n'y a que ceux qui savent qui ne savent pas qu'ils savent...
    Libere-toi hacker, GNU's Not Unix!!!

  5. #5
    Modérateur

    Profil pro
    Inscrit en
    août 2006
    Messages
    974
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : août 2006
    Messages : 974
    Points : 1 346
    Points
    1 346
    Par défaut
    En cherchant autre chose, je suis tombé sur la fonction popcnt, qui compte le nombre de bits à 1. La solution Fortran 2008 au problème est donc simplement :

    Puissance2 = popcnt(abs(Nombre)) == 1

  6. #6
    Membre éclairé Avatar de genteur slayer
    Homme Profil pro
    Développeur informatique
    Inscrit en
    juin 2002
    Messages
    710
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : juin 2002
    Messages : 710
    Points : 825
    Points
    825
    Par défaut
    joli!!!!
    il n'y a que ceux qui savent qui ne savent pas qu'ils savent...
    Libere-toi hacker, GNU's Not Unix!!!

  7. #7
    Membre régulier Avatar de moomba
    Profil pro
    Inscrit en
    avril 2007
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : avril 2007
    Messages : 134
    Points : 104
    Points
    104
    Par défaut
    Désolé du retard (encore une fois)

    Sylvain Bergeron

    Superbe effectivement.
    Malheureusement, cette fonction n'est pas intresec à tous les compilateurs, et je doit respecter la norme 95 afin que le code soir portable (surtout sur les clusters de calculs)... Je la garde donc dans un coin

    genteur slayer

    Effectivement, la boucle à 1000 est un peu exagérée
    Dans mon cas, un nombre négatif n'aurai pas passé les tests du début du programme (une valeur négative est interdite ici), donc je ne m'en suis pas vraiment préoccupé.

    Excellent l'idée du log, je vais utiliser celle çi. En commentant au dessus, les suivants n'auront pas de mal à comprendre.


    Merci beaucoup à tous les deux
    "Celui qui à le pouvoir de faire le mal, mais qui ne le fait pas, celui là est le prince de l'univers." (shakespeare)

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 11/02/2014, 11h50
  2. Réponses: 4
    Dernier message: 28/06/2007, 01h28
  3. Une page test pour flash player
    Par koKoTis dans le forum Flash
    Réponses: 11
    Dernier message: 02/12/2006, 12h49
  4. Réponses: 7
    Dernier message: 09/11/2006, 18h57
  5. Quel outil de test pour une appli web ?
    Par Arnard dans le forum Tests et Performance
    Réponses: 7
    Dernier message: 31/10/2006, 09h24

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