Connaître le rang d'un bit à 1 dans un mot.

Forum traitant des automates industriels de marque Siemens.
Avatar du membre
Béryl
Mi homme - Mi automate
Mi homme - Mi automate
Messages : 1953
Enregistré le : 20 oct. 2015, 12:00
Localisation : localhost

Connaître le rang d'un bit à 1 dans un mot.

Message par Béryl »

Amis cyborgs, bonjour !

Je me prends la tête sur une routine que j'arrive pas à pondre comme je veux en list sur Step 7 (CPU 312).
J'ai un mot dont je fais une rotation (le bit 15 est renvoyé dans le 0) chaque seconde.
Un seul bit est actif, le mot a donc toujours une valeur de puissance de 2.
Je voudrais connaître le rang du bit actif à un moment donné.
Ex : MW30=8, c'est donc le 4ème bit qui est à 1, la routine me renvoie la valeur 4.
Je pourrais faire une boucle avec un compteur, vous me direz, mais je suis sûr qu'il y a une méthode plus pratique/courte/facile.

Z'en pensez quoi ?
Avatar du membre
itasoft
Mi homme - Mi automate
Mi homme - Mi automate
Messages : 7803
Enregistré le : 20 oct. 2015, 10:15
Localisation : Lyon
Contact :

Re: Connaître le rang d'un bit à 1 dans un mot.

Message par itasoft »

direct sans boucle: n=log(W) / log(2)
--------
Exemple : %MW0=n° du seul bit à 1 dans %MW1

%MW0:=REAL_TO_INT(LOG(INT_TO_REAL(%MW1))/LOG(2.0));

-------avec boucle------
%MW0:=-1;
WHILE %MW1<>0 DO
%MW0:=%MW0+1;
%MW1:=SHR(%MW1,1);
END_WHILE;
Modifié en dernier par itasoft le 23 août 2025, 08:25, modifié 3 fois.
Automaticien privé (de tout)
itasoft@free.fr
Avatar du membre
Béryl
Mi homme - Mi automate
Mi homme - Mi automate
Messages : 1953
Enregistré le : 20 oct. 2015, 12:00
Localisation : localhost

Re: Connaître le rang d'un bit à 1 dans un mot.

Message par Béryl »

Merci Ita !
Ça s'annonce coton en list, mais ça se joue !
MiGaNuTs
Mi homme - Mi automate
Mi homme - Mi automate
Messages : 1572
Enregistré le : 12 nov. 2015, 21:02
Localisation : 45 - Loiret
Contact :

Re: Connaître le rang d'un bit à 1 dans un mot.

Message par MiGaNuTs »

Sinon une bonne vieille boucle de 0 a 15 avec des divisions par 2 ou des décalages a droite c'est simple, (re)lisible et ca marche.
Se faire des noeuds au cerveau pour le plaisir c'est rigolo 5 minutes, mais qd il faut revenir dessus x années plus tard parfois on regrete.
Avatar du membre
JC87
Mi homme - Mi automate
Mi homme - Mi automate
Messages : 2230
Enregistré le : 20 oct. 2015, 13:00
Localisation : Nouvelle Aquitaine

Re: Connaître le rang d'un bit à 1 dans un mot.

Message par JC87 »

Béryl a écrit : 21 août 2025, 15:09 Merci Ita !
Ça s'annonce coton en list, mais ça se joue !
Faut le faire en SCL, ça devrait pouvoir s'écrire quasiment tel quel.

JC
"On veut faire du zéro défaut mais on a zéro bonhomme et zéro budget, et bien à la fin on a zéro résultat..."
Avatar du membre
Béryl
Mi homme - Mi automate
Mi homme - Mi automate
Messages : 1953
Enregistré le : 20 oct. 2015, 12:00
Localisation : localhost

Re: Connaître le rang d'un bit à 1 dans un mot.

Message par Béryl »

JC87 a écrit : 21 août 2025, 15:47 Faut le faire en SCL, ça devrait pouvoir s'écrire quasiment tel quel.
Sur une vieille CPU 312 sous Step7 V5, pas trop le choix !
Je laisse tomber les logarithmes en list, ça compile pas (il faut un bloc standard Siemens).
steph68
Codeur fou
Codeur fou
Messages : 275
Enregistré le : 21 oct. 2015, 08:23

Re: Connaître le rang d'un bit à 1 dans un mot.

Message par steph68 »

Salut,

Soit un FC que tu nommes par exemple FFS_WORD (Find First Set sur un WORD) avec en entrée une variable "Bits" de type WORD, une variable temporaire "x" de type WORD également, et le résultat (dans la rubrique RETURN de l'interface) "RET_VAL" de type INT :

Code : Tout sélectionner

      L     #Bits
      PUSH  
      NEGI  
      UW                                // isolation du premier bit à 1 (= Bits AND -Bits)
      L     -1
      SPZ   L4			        // si pas de bit alors résultat = -1
      POP   

      T     #x
      UW    W#16#AAAA
      L     0
      SPZ   L1
      +     1

L1:   L     #x
      UW    W#16#CCCC
      POP   
      SPZ   L2
      +     2

L2:   L     #x
      UW    W#16#F0F0
      POP   
      SPZ   L3
      +     4

L3:   L     #x
      UW    W#16#FF00
      POP   
      SPZ   L4
      +     8

L4:   T     #RET_VAL
      SET   
      SAVE                              // pour que la broche ENO du bloc soit passante
Je n'ai pas testé mais cela devrait fonctionner ; tiens moi au courant.

Plus d'info sur le sujet ici : https://en.wikipedia.org/wiki/Find_first_set

@+
Avatar du membre
Béryl
Mi homme - Mi automate
Mi homme - Mi automate
Messages : 1953
Enregistré le : 20 oct. 2015, 12:00
Localisation : localhost

Re: Connaître le rang d'un bit à 1 dans un mot.

Message par Béryl »

Merci Steph68, mais... :o
Je vais essayer ton code et même le garder précieusement sous le coude s'il tourne bien.
Par contre, je ne vais pas m'en servir dans mon programme actuel, parce que ma petite routine est déjà bien assez compliquée pour ce qu'elle fait et je m'efforce de bien la commenter pour que le ou la prochain(e) qui y reviendra dans quelques années ne perde pas autant de neurones que moi en la codant :D
steph68
Codeur fou
Codeur fou
Messages : 275
Enregistré le : 21 oct. 2015, 08:23

Re: Connaître le rang d'un bit à 1 dans un mot.

Message par steph68 »

La simplification est peut-être de gérer un compteur de 0 à 15 qui reboucle pour ensuite positionner un bit en fonction de ce compteur plutôt que de le faire à l'envers... mais ne connaissant pas le contexte...

Code : Tout sélectionner

compteur := (compteur + 1) AND 15
ou bien

Code : Tout sélectionner

compteur := (compteur + 1) MOD 16
bit à partir d'un rang :

Code : Tout sélectionner

bit = SHL(1, rang);
tout ceci s'écrit très bien en LADDER et se passe de commentaires :mrgreen:

@+
steph68
Codeur fou
Codeur fou
Messages : 275
Enregistré le : 21 oct. 2015, 08:23

Re: Connaître le rang d'un bit à 1 dans un mot.

Message par steph68 »

pour compléter, ce que j'ai écris est plus ou moins cet algorithme (source https://graphics.stanford.edu/~seander/ ... htParallel)

Count the consecutive zero bits (trailing) on the right in parallel

Code : Tout sélectionner

unsigned int v;      // 32-bit word input to count zero bits on right
unsigned int c = 32; // c will be the number of zero bits on the right
v &= -signed(v);
if (v) c--;
if (v & 0x0000FFFF) c -= 16;
if (v & 0x00FF00FF) c -= 8;
if (v & 0x0F0F0F0F) c -= 4;
if (v & 0x33333333) c -= 2;
if (v & 0x55555555) c -= 1;
sauf que je l'ai fais dans l'autre sens.
une fois que tu as compris le concept, c'est facile à mettre en oeuvre.

@+
Répondre