vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
vb@rchiv Offline-Reader - exklusiv auf der vb@rchiv CD Vol.4  
 vb@rchiv Quick-Search: Suche startenErweiterte Suche starten   RSS-Feeds  | Newsletter  | Impressum  | Datenschutz  | vb@rchiv CD Vol.6  | Shop Copyright ©2000-2018
 
zurück
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:     [ Jetzt bewerten ]Views:  8.396 
ohne HomepageSystem:  Win2k, WinXP, Vista, Win7, Win8, Win10kein 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

Dieser Tipp wurde bereits 8.396 mal aufgerufen.

Voriger Tipp   |   Zufälliger Tipp   |   Nächster Tipp

Über diesen Tipp im Forum diskutieren
Haben Sie Fragen oder Anregungen zu diesem Tipp, können Sie gerne mit anderen darüber in unserem Forum diskutieren.

Neue Diskussion eröffnen

nach obenzurück


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.
 
   

Druckansicht Druckansicht Copyright ©2000-2018 vb@rchiv Dieter Otter
Alle 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.

Diese Seiten wurden optimiert für eine Bildschirmauflösung von mind. 1280x1024 Pixel