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 11.111 mal aufgerufen. Voriger Tipp | Zufälliger Tipp | Nächster Tipp
Anzeige
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. |
sevISDN 1.0 Überwachung aller eingehender Anrufe! Die DLL erkennt alle über die CAPI-Schnittstelle eingehenden Anrufe und teilt Ihnen sogar mit, aus welchem Ortsbereich der Anruf stammt. Weitere Highlights: Online-Rufident, Erkennung der Anrufbehandlung u.v.m. Tipp des Monats April 2024 Skyfloy Chart von Microsoft und dazu noch gratis Tutorial für Microsoft Chart Controls für Microsoft .NET Framework 3.5 Neu! sevCommand 4.0 Professionelle Schaltflächen im modernen Design! Mit nur wenigen Mausklicks statten auch Sie Ihre Anwendungen ab sofort mit grafischen Schaltflächen im modernen Look & Feel aus (WinXP, Office, Vista oder auch Windows 8), inkl. große Symbolbibliothek. |
||||||||||||||||
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. |