Manipulations de bits dans des tables.

Soyez le premier à donner votre avis sur cette source.

Vue 3 389 fois - Téléchargée 156 fois

Description

1 - Permet de réduire la place occupée (jusqu'à plus de 90%) par des indicateurs booléens, si l'on doit en manipuler beaucoup.
2 - Permet de travailler sur des "ensembles".

Source / Exemple :


Attribute VB_Name = "TableBool"
' REDLUPUS 2004 : manipulations de bits dans des tables.
' 1 - Permet de réduire la place occupée (jusqu'à plus de 90%) par
'     des indicateurs booléens, si l'on doit en manipuler beaucoup.
' 2 - Permet de travailler sur des "ensembles".
' remarque :
'       - La partie "Appels pour le positionnement des bits" est
'         surtout là pour illustrer les possibilités de la fonction
'         "RWCheckBit",
'       - La partie "Appels pour ensembles", et la procédure "SetModify",
'         quant à elles, cherchent à montrer une utilisation possible
'         des tables ainsi définies.

Option Explicit
'Option Base 1

' ===========================================================================
' Appels pour les ensembles
'
'   1 - Eléments d'un ensemble
'   AddToSet    ajoute un élément à l'ensemble
'   RemFmSet    retire un élément de l'ensemble
'   IsInSet     teste la présence d'un élément dans l'ensemble
'
'   2 - Modification d'ensembles
'   SetClr      remise à zéro d'un ensemble
'   SetUni      établit la réunion de deux ensembles
'   SetInt      établit l'intersection de deux ensembles
'   SetSub      établit la différence entre deux ensembles
'   SetNot      établit le complément d'une ensemble
'   SetCopy     Copie un ensemble
' -----------------------------------------------------------------------
  Public Sub AddToSet(ByRef T() As Long, ByVal P As Byte)
  Call RWCheckBit(T, P, 1): End Sub
' -----------------------------------------------------------------------
  Public Sub RemFmSet(ByRef T() As Long, ByVal P As Byte)
  Call RWCheckBit(T, P, 0): End Sub
' -----------------------------------------------------------------------
  Public Function IsInSet(ByRef T() As Long, ByVal P As Byte) As Boolean
  IsInSet = RWCheckBit(T, P): End Function
' -----------------------------------------------------------------------
  Public Sub SetClr(ByRef T() As Long)
  Call SetModify(T, T, T, 0): End Sub
' -----------------------------------------------------------------------
  Public Sub SetUni(ByRef T1() As Long, T2() As Long, T3() As Long)
  Call SetModify(T1, T2, T3, 1): End Sub
' -----------------------------------------------------------------------
  Public Sub SetInt(ByRef T1() As Long, T2() As Long, T3() As Long)
  Call SetModify(T1, T2, T3, 2): End Sub
' -----------------------------------------------------------------------
  Public Sub SetSub(ByRef T1() As Long, T2() As Long, T3() As Long)
  Call SetModify(T1, T2, T3, 3): End Sub
' -----------------------------------------------------------------------
  Public Sub SetNot(ByRef T1() As Long)
  Call SetModify(T1, T1, T1, 4): End Sub
' -----------------------------------------------------------------------
  Public Sub SetCopy(ByRef T1() As Long, ByRef T3() As Long)
  Call SetModify(T1, T1, T3, 5): End Sub

' ===========================================================================
' Appels pour le positionnement des bits :
'
'   BT      teste le bit P
'   BTS     teste le bit P et le met à "True"
'   BTR     teste le bit P et le met à "False"
'   BTC     teste le bit P et le change
' -----------------------------------------------------------------------
  Public Function BT(ByRef T() As Long, ByVal P As Byte) As Boolean
  BT = RWCheckBit(T, P): End Function
' -----------------------------------------------------------------------
  Public Function BTS(ByRef T() As Long, ByVal P As Byte) As Boolean
  BTS = RWCheckBit(T, P, 1): End Function
' -----------------------------------------------------------------------
  Public Function BTR(ByRef T() As Long, ByVal P As Byte) As Boolean
  BTR = RWCheckBit(T, P, 0): End Function
' -----------------------------------------------------------------------
  Public Function BTC(ByRef T() As Long, ByVal P As Byte) As Boolean
  BTC = RWCheckBit(T, P, 2): End Function

' ===========================================================================
  Private Function RWCheckBit(ByRef T() As Long, _
                              ByVal P As Byte, _
                     Optional ByVal C As Byte = 3) As Boolean
' -----------------------------------------------------------------------
' Positionne un bit dans une table de booléens. Dans tous les cas,
' utilisée comme fonction, retourne la valeur du bit correspondant,
' avant l'opération demandée.
'   T           Tableau formés de blocs de 4 octets (Long). En fait, afin
'               d'éviter les problèmes de débordements sur le bit signe,
'               seuls 31 des 32 octets disponibles sont utilisés
'   P           Position (ou n°) du bit dont la valeur doit être affectée
'   C           Commande optionnelle :
'                   0       mettre à "False"
'                   1       mettre à "True"
'                   2       compléménté
'                   3       (défaut) pas d'opération, lecture simple de
'                           la valeur du bit.
' ===========================================================================
Const BkSize As Byte = 31   ' taille utile d'un bloc

Dim BitMsk As Long          ' masque correspondant à "P"
Dim NumBk As Byte           ' n° du bloc de 4 octets

'si P hors limites, selon "T", on sort.
If P > ((UBound(T) - LBound(T) + 1) * BkSize) Then Exit Function

Let NumBk = (P - 1) \ BkSize + LBound(T)
' masque relatif au bloc "NumBk", correspondant à la position "P"
Let BitMsk = 2 ^ ((P - 1) Mod BkSize)
RWCheckBit = (T(NumBk) And BitMsk) <> 0
Select Case C
    Case 0: Let T(NumBk) = T(NumBk) And Not BitMsk
    Case 1: Let T(NumBk) = T(NumBk) Or BitMsk
    Case 2: Let T(NumBk) = T(NumBk) Xor BitMsk
    End Select
End Function

' ===========================================================================
  Private Sub SetModify(ByRef T1() As Long, _
                        ByRef T2() As Long, _
                        ByRef T3() As Long, _
                        ByVal C As Byte)
' -----------------------------------------------------------------------
' Effectue une opération entre les ensembles T1 et T2 et met le résultat
' dans T3. Les déclarations de T1, T2 et T3 doivent être identiques.
'   T1, T2      "ensembles" à traiter
'   T3          "ensemble" résultat
'   C           commande :
'                   0       remise à zéro
'                   1       réunion
'                   2       intersection
'                   3       T1 - T2
'                   4       complément de T1
'                   5       copie
' ===========================================================================
Const Cmp1 As Long = &H7FFFFFFF ' valeur pour complément à 1

Dim I As Byte               ' indice de boucle

For I = 1 To UBound(T1)
    Select Case C
        Case 0: Let T3(I) = 0
        Case 1: Let T3(I) = T1(I) Or T2(I)
        Case 2: Let T3(I) = T1(I) And T2(I)
        Case 3: Let T3(I) = T1(I) And (T2(I) Xor Cmp1)
        Case 4: Let T1(I) = T1(I) Xor Cmp1
        Case 5: Let T3(I) = T1(I)
        End Select
    Next I
End Sub

Conclusion :


Seule la procédure "RWCheckBit" est vraiment l'objet de ce code.
- La partie "Appels pour le positionnement des bits" est surtout là pour en illustrer les possibilités.
- La partie "Appels pour ensembles", et la procédure "SetModify", quant à elles, cherchent à montrer une utilisation possible.

Pour ceux qui sont peu familiers avec les booléens, un fichier TableBool.txt figurant dans le "zip", essaie d'apporter quelques explications, qui auraient été trop lourdes dans le code.

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

Messages postés
5
Date d'inscription
lundi 8 mars 2004
Statut
Membre
Dernière intervention
17 août 2004

Bonjour ShadowMaster, Bonjour Vlad2i.

ShadowMaster, tu as raison, "option Base 1" est, sommes toute, une contrainte inutile. J'ai donc modifié mon code dans ce sens. On n'est donc plus obligé de déclarer le tableau T(1..n).

Vlad2i, tu as raison, on peut simplifier. En fait, la première version positionnait le bit, en accord avec une valeur passée en argument, ce qui me faisait positionner le bit en 2 temps :
1 - RAZ ("and 0")
2 - positionnement ("or <valeur du bit")
A présent, ce n'est plus nécessaire, j'ai donc modifié le "case" en ce sens.
Toutefois, les valeurs de "C" ont été choisies de telle sorte que l'on peut toujours appeler la procédure, sans avoir testé au préalable la valeur que devra avoir le bit. il suffit de l'appeler ainsi :
RWCheckBit(T,P,abs(MonBooléen))
Quant à "Maxp", variable servant une seule fois (quel luxe !) je l'ai virée comme indiqué précédemment.

Merci beaucoup pour vos remarques qui me permettent de m'améliorer.
Messages postés
184
Date d'inscription
mercredi 27 novembre 2002
Statut
Membre
Dernière intervention
18 août 2005

merci merci, je connais option explicit, je connais les tableaux pas besoin de m'expliquer :D
Par contre option base 1 moué ça peu avoir son utilité mais bon, pas indispensable, on peu declarer son tableau comme ça:
Dim T (1 to 5) as ...
Messages postés
5
Date d'inscription
lundi 8 mars 2004
Statut
Membre
Dernière intervention
17 août 2004

Salut vlad2i,

J'écivais en même temps que toi ! lol !

Tu as raison : Je pourrais commencer par "virer" la variable "MaxP", par exemple. Enfin ! je ferai mieux (enfin... peut-être... :) ) la prochaine fois (l'espoir fait vivre, dit-on).

Encore merci à tous.
Messages postés
5
Date d'inscription
lundi 8 mars 2004
Statut
Membre
Dernière intervention
17 août 2004

Bonjour ShadowMaster.

Option Explicit est ici sans grande importance. Je la mets systématiquement car elle force à déclarer "explicitement" doute variable. Si on omet d'en déclarer une, cela provoque une erreur à la compilation. Je trouve simplement que c'est une bonne précaution, pour une bonne habitude.

Option Base 1, par contre est importante dans ce code. Elle fixe l'indice inférieur par défaut d'un tableau. Sans cette option, la valeur infèrieure d'indice pour un tableau est 0.

Dans ce cas :

dim T(5) as... (ce que tu veux...) correspondrait au tableau T(0), T(1), T(2), T(3), T(4).

avec option base 1

dim T(5) as... (ce que tu veux...) correspond au tableau T(1), T(2), T(3), T(4), T(5).

or "Ubound" renvoie, non pas une taille, mais l'indice le plus élevé de la dimension demandée (la première, par défaut, dans ce code). De même "Lbound" retourne l'indice inférieur.

Moralité : si on prend l'instruction

Let MaxP=Ubound(T)*BkSize

celle-ci suppose que le premier élément de T est T(1).
On peut s'affranchir de l'"option base" en la remplaçant par :

Let MaxP=(Ubound(T)-Lbound(T)+1)*BkSize

Les autres instructions seraient à modifier dans le même ordre d'idée : là où on adresse T(n), par exemple, il faudrait adresser T(Lbound(T)+n-1) et ainsi de suite.

Il me semblait donc plus "léger" (bon !) de fixer l'option base (plus pour dire que je la fixais, d'ailleurs, ce que tu as fort bien vu, que pour la fixer à "1" proprement dit) et d'avoir un code un peu moins lourd.

Pour ce qui est de l'envoi réseau, ce n'est pas vraiment un domaine que je pratique. Si tu veux, tu peux m'indiquer souci en me contactant directement. Pas la peine de développer trop, dans un premier temps, juste histoire de me faire une idée sur le problème.

Espérant avoir apporté une petite contribution, je vous remercie pour l'intérêt que vous y portez.
Messages postés
285
Date d'inscription
mercredi 20 août 2003
Statut
Membre
Dernière intervention
13 février 2005

Il y a Option Base 0 et Option Implicit, qui sont par défaut

Option Base 1 définit le premier élément d'un tableau à 1 (au lieu de 0)
Option Explicit oblige à déclarer les variables (au lieu de les supposer en variant)

Valà

Sinon un bon code, bien que l'on doit pouvoir faire plus léger qd meme :)
Afficher les 7 commentaires

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.