vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#

https://www.vbarchiv.net
Rubrik: Variablen/Strings   |   VB-Versionen: VB200823.03.09
SetBits, GetBits: Zugriff auf die Bits numerischer Variablen

Ein Modul mit SetBits- und Getbits-Überladungen für den Zugriff auf die Bits, die in numerischen Variablen enthalten sind

Autor:   Manfred BohnBewertung:  Views:  11.085 
ohne HomepageSystem:  Win2k, WinXP, Win7, Win8, Win10, Win11kein Beispielprojekt 

Bei den integrierten numerischen VB-Datentypen fehlt jeweils die 'SetBits' und 'GetBits'-Methode, durch die eine Bitfolge als Instanz der Klasse 'BitArray' abgerufen bzw. gesetzt werden kann.

Die 'BitConverter'-Klasse enthält alle benötigten Methoden, so dass die Erstellung eines Moduls, das die Erweiterungen (typspezifische Überladungen) enthält, eine einfache Fleißarbeit ist.

Bei den 'SetBits'-Überladungen kann durch den optionalen Parameter 'UseAny' festgelegt werden, ob die Länge des als Parameter übergebenen 'Bitarray' an die erforderliche Länge des Datentyps angepasst wird (Null-Bits anhängen bzw. Bits abschneiden) oder ob ggf. eine Ausnahme ausgelöst wird.

Boolsche Variable werden auf ein einzelnes Bit abgebildet!

Zur Demonstration sind im Modul 'modBitFunctions' zusätzlich die 'GetBit'/'SetBit'-Überladungen für Integer und Decimal enthalten, durch die ein direkter, indizierter Bit-Zugriff möglich ist.

Die 'Bits2String'- und 'String2Bits'-Erweiterungen dienen zur Veranschaulichung des Bit-Inhaltes numerischer Variablen.

Option Strict On
Option Explicit On
Option Infer Off
 
Imports System ' BitConverter-Klasse 
Imports System.Collections ' BitArray-Klasse
Imports System.Runtime.CompilerServices ' Extension-Attribut 
 
Namespace Bit_Functions
 
  ''' <summary>Bit-Bearbeitung durch BitArrays</summary>
  Public Module mod_Set_Get_Bits
    ' ================================================================
    ' GetBits-Überladungen
    ' ================================================================
 
    ''' <summary>Boolean-Bit in Bitarray eintragen</summary>
    ''' <param name="arg">Boolean-Variable</param>
    ''' <returns>Bitarray (1 Bit)</returns>
    <Extension()> _
    Public Function GetBits(ByVal arg As Boolean) As BitArray
      Dim ba As New BitArray(1) ' Length!!
      ba(0) = arg : Return ba
    End Function
 
    ''' <summary>Byte-Bits in Bitarray eintragen</summary>
    ''' <param name="arg">Byte-Variable</param>
    ''' <returns>Bitarray (8 Bits)</returns>
    <Extension()> _
    Public Function GetBits(ByVal arg As Byte) As BitArray
      Dim byt(0) As Byte ' Ubound!!
      byt(0) = arg : Return New BitArray(byt)
    End Function
 
    ' ab hier wird der BitConverter eingesetzt:
    ' -----------------------------------------
 
    ''' <summary>Char-Bits in Bitarray eintragen</summary>
    ''' <param name="arg">Char-Variable</param>
    ''' <returns>Bitarray (8 Bits)</returns>
    <Extension()> _
    Public Function GetBits(ByVal arg As Char) As BitArray
      Return New BitArray(BitConverter.GetBytes(arg))
    End Function
 
    ''' <summary>Short-Bits in Bitarray eintragen</summary>
    ''' <param name="arg">Short-Variable</param>
    ''' <returns>Bitarray (16 Bits)</returns>
    <Extension()> _
    Public Function GetBits(ByVal arg As Short) As BitArray
      Return New BitArray(BitConverter.GetBytes(arg))
    End Function
 
    ''' <summary>UShort-Bits in Bitarray eintragen</summary>
    ''' <param name="arg">UShort-Variable</param>
    ''' <returns>Bitarray (16 Bits)</returns>
    <Extension()> _
    Public Function GetBits(ByVal arg As UShort) As BitArray
      Return New BitArray(BitConverter.GetBytes(arg))
    End Function
 
    ''' <summary>Integer-Bits in Bitarray eintragen</summary>
    ''' <param name="arg">Integer-Variable</param>
    ''' <returns>Bitarray (32 Bits)</returns>
    <Extension()> _
    Public Function GetBits(ByVal arg As Integer) As BitArray
      Return New BitArray(BitConverter.GetBytes(arg))
    End Function
 
    ''' <summary>UInteger-Bits in Bitarray eintragen</summary>
    ''' <param name="arg">UInteger-Variable</param>
    ''' <returns>Bitarray (32 Bits)</returns>
    <Extension()> _
    Public Function GetBits(ByVal arg As UInteger) As BitArray
      Return New BitArray(BitConverter.GetBytes(arg))
    End Function
 
    ''' <summary>Long-Bits in Bitarray eintragen</summary>
    ''' <param name="arg">Long-Variable</param>
    ''' <returns>Bitarray (64 Bits)</returns>
    <Extension()> _
    Public Function GetBits(ByVal arg As Long) As BitArray
      Return New BitArray(BitConverter.GetBytes(arg))
    End Function
 
    ''' <summary>ULong-Bits in Bitarray eintragen</summary>
    ''' <param name="arg">ULong-Variable</param>
    ''' <returns>Bitarray (64 Bits)</returns>
    <Extension()> _
    Public Function GetBits(ByVal arg As ULong) As BitArray
      Return New BitArray(BitConverter.GetBytes(arg))
    End Function
 
    ''' <summary>Single-Bitmuster in Bitarray eintragen</summary>
    ''' <param name="arg">Single-Variable</param>
    ''' <returns>Bitarray (32 Bits)</returns>
    <Extension()> _
    Public Function GetBits(ByVal arg As Single) As BitArray
      Return New BitArray(BitConverter.GetBytes(arg))
    End Function
 
    ''' <summary>Double-Bitmuster in Bitarray eintragen</summary>
    ''' <param name="arg">Double-Variable</param>
    ''' <returns>Bitarray (64 Bits)</returns>
    <Extension()> _
    Public Function GetBits(ByVal arg As Double) As BitArray
      Return New BitArray(BitConverter.GetBytes(arg))
    End Function
 
    ''' <summary>Decimal-Bits in Bitarray eintragen</summary>
    ''' <param name="arg">Decimal-Variable</param>
    ''' <returns>Bitarray (128 Bits)</returns>
    <Extension()> _
    Public Function GetBits(ByVal arg As Decimal) As BitArray
      Return New BitArray(Decimal.GetBits(arg))
    End Function
    ' =================================================================
    ' SetBits-Überladungen
    ' =================================================================
 
    ''' <summary>Bitarray in Boolean eintragen (1 Bit!!)</summary>
    ''' <param name="vl">Ziel-Variable (wird überschrieben)</param>
    ''' <param name="ba">einzutragendes Bitarray</param>
    ''' <param name="UseAny">Arraylänge ggf. anpassen?</param>
    <Extension()> _
    Public Sub SetBits(ByRef vl As Boolean, _
      ByVal ba As BitArray, _
      Optional ByVal UseAny As Boolean = False)
 
      GetBytes(ba, 1, UseAny)
      vl = ba(0)
    End Sub
 
    ''' <summary>Bitarray in Byte-Variable eintragen (8 Bit)</summary>
    ''' <param name="vl">Ziel-Variable (wird überschrieben)</param>
    ''' <param name="ba">einzutragendes Bitarray</param>
    ''' <param name="UseAny">Arraylänge ggf. anpassen?</param>
    <Extension()> _
    Public Sub SetBits(ByRef vl As Byte, _
      ByVal ba As BitArray, _
      Optional ByVal UseAny As Boolean = False)
 
      vl = GetBytes(ba, 8, UseAny)(0)
    End Sub
 
    ' ab hier wird der BitConverter eingesetzt:
    ' -----------------------------------------
 
    ''' <summary>Bitarray in Short-Variable eintragen (16 Bits)</summary>
    ''' <param name="vl">Ziel-Variable (wird überschrieben)</param>
    ''' <param name="ba">einzutragendes Bitarray</param>
    ''' <param name="UseAny">Arraylänge ggf. anpassen?</param>
    <Extension()> _
    Public Sub SetBits(ByRef vl As Short, _
      ByVal ba As BitArray, _
      Optional ByVal UseAny As Boolean = False)
 
      vl = BitConverter.ToInt16(GetBytes(ba, 16, UseAny), 0)
    End Sub
 
    ''' <summary>Bitarray in UShort-Variable eintragen</summary>
    ''' <param name="vl">Ziel-Variable (wird überschrieben)</param>
    ''' <param name="ba">einzutragendes Bitarray</param>
    ''' <param name="UseAny">Arraylänge ggf. anpassen?</param>
    <Extension()> _
    Public Sub SetBits(ByRef vl As UShort, _
      ByVal ba As BitArray, _
      Optional ByVal UseAny As Boolean = False)
 
      vl = BitConverter.ToUInt16(GetBytes(ba, 16, UseAny), 0)
    End Sub
 
    ''' <summary>Bitarray in Integer-Variable eintragen (32 Bits)</summary>
    ''' <param name="vl">Ziel-Variable (wird überschrieben)</param>
    ''' <param name="ba">einzutragendes Bitarray</param>
    ''' <param name="UseAny">Arraylänge ggf. anpassen?</param>
    <Extension()> _
    Public Sub SetBits(ByRef vl As Integer, _
      ByVal ba As BitArray, _
      Optional ByVal UseAny As Boolean = False)
 
      vl = BitConverter.ToInt32(GetBytes(ba, 32, UseAny), 0)
    End Sub
 
    ''' <summary>Bitarray in UInteger-Variable eintragen (32 Bits)</summary>
    ''' <param name="vl">Ziel-Variable (wird überschrieben)</param>
    ''' <param name="ba">einzutragendes Bitarray</param>
    ''' <param name="UseAny">Arraylänge ggf. anpassen?</param>
    <Extension()> _
    Public Sub SetBits(ByRef vl As UInteger, _
      ByVal ba As BitArray, _
      Optional ByVal UseAny As Boolean = False)
 
      vl = BitConverter.ToUInt32(GetBytes(ba, 32, UseAny), 0)
    End Sub
 
    ''' <summary>Bitarray in Long-Variable eintragen (64 Bits)</summary>
    ''' <param name="vl">Ziel-Variable (wird überschrieben)</param>
    ''' <param name="ba">einzutragendes Bitarray</param>
    ''' <param name="UseAny">Arraylänge ggf. anpassen?</param>
    <Extension()> _
    Public Sub SetBits(ByRef vl As Long, _
      ByVal ba As BitArray, _
      Optional ByVal UseAny As Boolean = False)
 
      vl = BitConverter.ToInt64(GetBytes(ba, 64, UseAny), 0)
    End Sub
 
    ''' <summary>Bitarray in ULong-Variable eintragen (64 Bits)</summary>
    ''' <param name="vl">Ziel-Variable (wird überschrieben)</param>
    ''' <param name="ba">einzutragendes Bitarray</param>
    ''' <param name="UseAny">Arraylänge ggf. anpassen?</param>
    <Extension()> _
    Public Sub SetBits(ByRef vl As ULong, _
      ByVal ba As BitArray, _
      Optional ByVal UseAny As Boolean = False)
 
      vl = BitConverter.ToUInt64(GetBytes(ba, 64, UseAny), 0)
    End Sub
 
    ''' <summary>Bitarray in Single-Variable eintragen (32 Bits)</summary>
    ''' <param name="vl">Ziel-Variable (wird überschrieben)</param>
    ''' <param name="ba">einzutragendes Bitarray</param>
    ''' <param name="UseAny">Arraylänge ggf. anpassen?</param>
    <Extension()> _
    Public Sub SetBits(ByRef vl As Single, _
      ByVal ba As BitArray, _
      Optional ByVal UseAny As Boolean = False)
 
      vl = BitConverter.ToSingle(GetBytes(ba, 32, UseAny), 0)
    End Sub
 
    ''' <summary>Bitarray in Double-Variable eintragen (64 Bits)</summary>
    ''' <param name="vl">Ziel-Variable (wird überschrieben)</param>
    ''' <param name="ba">einzutragendes Bitarray</param>
    ''' <param name="UseAny">Arraylänge ggf. anpassen?</param>
    <Extension()> _
    Public Sub SetBits(ByRef vl As Double, _
      ByVal ba As BitArray, _
      Optional ByVal UseAny As Boolean = False)
 
      vl = BitConverter.ToDouble(GetBytes(ba, 64, UseAny), 0)
    End Sub
 
    ''' <summary>Bitarray in Decimal-Variable eintragen (128 Bits)</summary>
    ''' <param name="vl">Ziel-Variable (wird überschrieben)</param>
    ''' <param name="ba">einzutragendes Bitarray</param>
    ''' <param name="UseAny">Arraylänge ggf. anpassen?</param>
    <Extension()> _
    Public Sub SetBits(ByRef vl As Decimal, _
      ByVal ba As BitArray, _
      Optional ByVal UseAny As Boolean = False)
 
      ' BitArray --> ByteArray
      Dim byt() As Byte = GetBytes(ba, 128, UseAny)
      ' ByteArray --> IntegerArray
      Dim intarray(3) As Integer
      For i As Integer = 0 To 3
        intarray(i) = BitConverter.ToInt32(byt, i * 4)
      Next i
      ' IntegerArray --> Decimal
      vl = New Decimal(intarray)
    End Sub
 
    Private Function GetBytes(ByRef ba As BitArray, _
      ByVal Length As Integer, _
      ByVal UseAny As Boolean) As Byte()
 
      ' Hilfsfunktion SetBits-Überladungen
      ' BitArray kontrolliert in ein Byte-Array übertragen
 
      Dim ok As Boolean = True
      If ba Is Nothing Then ok = False
      If Length < 1 Or Length > 128 Then ok = False
      If ba.Length < 1 Or ba.Length > 128 Then ok = False
      If Not ok Then
        Throw New ArgumentException("Ungeeigneter oder fehlender Parameter")
      End If
 
      If ba.Length <> Length Then
        If Not UseAny Then
          Throw New ArgumentException("Exakt " + CStr(Length) + " Bits werden benötigt")
        End If
      End If
 
      If Length Mod 8 <> 0 Then
        If Not UseAny Then
          Throw New ArgumentException("Bit-Länge muss ein Vielfaches von 8 sein")
        End If
        Length = ((Length \ 8) + 1) * 8
      End If
 
      ' ggf. Bits abschneiden oder 0-Bits hinzufügen
      ba.Length = Length
 
      ' Bits --> Bytes
      Dim Bytes(ba.Length \ 8 - 1) As Byte
      ba.CopyTo(Bytes, 0)
 
      ' Rückgabe
      Return Bytes
    End Function
    ' ==================================================================
    ' SetBit / GetBit: 
    ' Direkter, indizierter Zugriff auf ein Variablen-Bit im 
    ' rufenden Programm (Beispiele für Integer-, Decimal-Erweiterung)
    ' ==================================================================
 
    ''' <summary>Eintragen eines Bit in eine Integer-Variable</summary>
    ''' <param name="arg">Integer-Variable (Ziel)</param>
    ''' <param name="Index">Bit-Index (0-31)</param>
    ''' <param name="BitValue">einzutragender Bit-Wert</param>
    <Extension()> _
    Public Sub SetBit(ByRef arg As Integer, ByVal Index As Integer, _
      ByVal BitValue As Boolean)
 
      If Index < 0 Or Index > 31 Then
        Throw New ArgumentOutOfRangeException _
          ("Der Bit-Index liegt ausserhalb der Breite des Datentyps")
      End If
      Dim ba As BitArray = arg.GetBits
      ba(Index) = BitValue : arg.SetBits(ba)
    End Sub
 
    ''' <summary>Abfragen eines Bits in einer Integer-Variable</summary>
    ''' <param name="arg">Integer-Variable (Quelle)</param>
    ''' <param name="Index">Bit-Index (0-31)</param>
    ''' <returns>aktueller Wert des Bits</returns>
    <Extension()> _
    Public Function GetBit(ByVal arg As Integer, ByVal Index As Integer) As Boolean
      If Index < 0 Or Index > 31 Then
        Throw New ArgumentOutOfRangeException _
          ("Der Bit-Index liegt ausserhalb der Breite des Datentyps")
      End If
      Dim ba As BitArray = arg.GetBits
      Return ba(Index)
    End Function
 
    ''' <summary>Eintragen eines Bit in eine Decimal-Variable</summary>
    ''' <param name="arg">Decimal-Variable (Ziel)</param>
    ''' <param name="Index">Bit-Index (0-127)</param>
    ''' <param name="BitValue">einzutragender Bit-Wert</param>
    <Extension()> _
    Public Sub SetBit(ByRef arg As Decimal, ByVal Index As Integer, _
      ByVal BitValue As Boolean)
 
      If Index < 0 Or Index > 127 Then
        Throw New ArgumentOutOfRangeException _
          ("Der Bit-Index liegt ausserhalb der Breite des Datentyps")
      End If
      Dim ba As BitArray = arg.GetBits
      ba(Index) = BitValue : arg.SetBits(ba)
    End Sub
 
    ''' <summary>Abfragen eines Bits in einer Decimal-Variable</summary>
    ''' <param name="arg">Decimal-Variable (Quelle)</param>
    ''' <param name="Index">Bit-Index (0-127)</param>
    ''' <returns>aktueller Wert des Bits</returns>
    <Extension()> _
    Public Function GetBit(ByVal arg As Decimal, ByVal Index As Integer) As Boolean
      If Index < 0 Or Index > 127 Then
        Throw New ArgumentOutOfRangeException _
          ("Der Bit-Index liegt ausserhalb der Breite des Datentyps")
      End If
      Dim ba As BitArray = arg.GetBits
      Return ba(Index)
    End Function
    ' =========================================================
    '  Umwandlung: BitArray <--> 0/1-String
    ' =========================================================
 
    ''' <summary>Inhalt eines Bitarray in 0/1-String eintragen</summary>
    ''' <param name="ba">Bitarray (Quelle)</param>
    ''' <param name="ByteSeparator">
    ''' Gruppen von 8 Bits durch Space trennen?</param>
    ''' <returns>Bit-String</returns>
    <Extension()> _
    Public Function Bits2String(ByVal ba As BitArray, _
      Optional ByVal ByteSeparator As Boolean = True) As String
 
      If ba Is Nothing Then Return Nothing
      If ba.Length < 1 Then Return ""
      Dim str As String = ""
      For i As Integer = 0 To ba.Length - 1
        If ba(i) Then str &= "1" Else str &= "0"
        If ByteSeparator Then
          If (i + 1) Mod 8 = 0 Then str &= " "
        End If
      Next i
      Return str.Trim
    End Function
 
    ''' <summary>Ein Bit-String (Charakter '1'=true, sonst false) wird 
    ''' in ein Bitarray eingetragen-Spaces werden zuvor entfernt</summary>
    ''' <param name="bits">Bit-String (Quelle)</param>
    ''' <returns>Bitarray</returns>
    <Extension()> _
    Public Function String2Bits(ByVal bits As String) As BitArray
      If String.IsNullOrEmpty(bits) Then Return Nothing
      Dim Str As String = bits.Replace(" ", "").Trim
      If Str.Length = 0 Then Return Nothing
      Dim ba As New BitArray(Str.Length)
      For i As Integer = 0 To Str.Length - 1
        If Str = "1" Then ba(i) = True
      Next i
      Return ba
    End Function
  End Module
End Namespace

Einige Beispiele:

Public Sub Ex_BitFunctions()
 
  Console.WriteLine()
  Console.WriteLine("Beispiele für Bitmuster:")
  Console.WriteLine()
 
  ' Das 33. Bit in einer Decimal-Variable setzen und das
  ' Bitmuster in der Standardausgabe als String anzeigen
  Dim dec As Decimal = CDec(2 ^ 32)
  Console.WriteLine("Decimal-Bits: " + CStr(dec))
  Console.WriteLine(dec.GetBits.Bits2String())
 
  ' Die Bitfolge in eine zweite Decimal-Variable übertragen 
  Dim dec2 As Decimal
  dec2.SetBits(dec.GetBits)
  If dec2 <> CDec(2 ^ 32) Then Stop ' sollte nicht sein
 
  ' Das sechste Bit wird gesetzt (und wg. des
  ' negativen Vorzeichens auch alle folgenden Bits)
  Dim shrt As Short = -1S * CShort(2 ^ 5)
  Console.WriteLine("Short-Bits: " + CStr(shrt))
  Console.WriteLine(shrt.GetBits.Bits2String())
 
  ' Der UseAny-Parameter erlaubt das Eintragen der 
  ' 16-Short-Bits in die Long-Variable 
  ' Das Bitmuster des negativen Short-Wertes wird
  ' im Datentyp Long anders interpretiert
  Dim lng As Long
  lng.SetBits(shrt.GetBits, True)
  Console.WriteLine("Long-Bits: " + CStr(lng))
  Console.WriteLine(lng.GetBits.Bits2String())
 
  ' Das fünfte UND neunte Bit in 'Integ' wird gesetzt
  Dim integ As Integer = CInt(2 ^ 4) Or CInt(2 ^ 8)
  Console.WriteLine("Integer-Bits: " + CStr(integ))
  Console.WriteLine(integ.GetBits.Bits2String())
 
  ' Das neunte Bit wird gelöscht (null-basierter Index)
  integ.SetBit(8, False)
  Console.WriteLine("Integer-Bits: " + CStr(integ))
  Console.WriteLine(integ.GetBits.Bits2String())
 
  ' Kleinster von 0 unterscheidbarer Decimalwert
  ' im 15. Byte steht die Potenz des 
  ' Decimal-Skalierungs-Divisors (max. 28)
  dec = CDec(1.0E-28)
  Console.WriteLine("Decimal-Bits: " + CStr(dec))
  Console.WriteLine(dec.GetBits.Bits2String())
 
  ' IEEE-Bitmuster besteht aus Mantisse und Exponent!
  Dim sng As Single = 9999999.0!
  Console.WriteLine("Single-Bits: " + CStr(sng))
  Console.WriteLine(sng.GetBits.Bits2String())
 
End Sub



Anzeige

Kauftipp Unser Dauerbrenner!Diesen und auch alle anderen Tipps & Tricks finden Sie auch auf unserer aktuellen vb@rchiv  Vol.6

Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv!
- nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten
- Symbol-Galerie mit mehr als 3.200 Icons im modernen Look
Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m.
 
 
Copyright ©2000-2024 vb@rchiv Dieter OtterAlle Rechte vorbehalten.


Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.