Page 1 sur 2

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

Posté : 21 août 2025, 11:55
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 ?

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

Posté : 21 août 2025, 14:13
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;

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

Posté : 21 août 2025, 15:09
par Béryl
Merci Ita !
Ça s'annonce coton en list, mais ça se joue !

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

Posté : 21 août 2025, 15:35
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.

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

Posté : 21 août 2025, 15:47
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

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

Posté : 21 août 2025, 16:00
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).

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

Posté : 22 août 2025, 06:05
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

@+

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

Posté : 22 août 2025, 08:27
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

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

Posté : 22 août 2025, 14:25
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:

@+

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

Posté : 22 août 2025, 14:29
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.

@+