Setz n Bits zu EINER Zahl zusammen

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 17 Antworten in diesem Thema. Der letzte Beitrag () ist von Coder.

    Setz n Bits zu EINER Zahl zusammen

    Hallo zusammen,
    ich brauche bitte nochmal eure Hilfe.
    :)
    Ich muss eine VB.NET-Funktion (.NET Framework 4.8.1) schreiben, die n Bits zu einer Zahl (uint32) zusammensetzt.
    Die gelesenen Bits werden als eine Einheit betrachtet. Das bedeutet, nicht als separate Zahlen.

    Die Startposition ist immer Index 0.

    Beispiel 1
    Lies 16 Bits aus {1, 2}, also 0000 0001 0000 0010. Ergebnis ist 258.

    Beispiel 2
    Lies 24 Bits aus {1, 2, 0}, also 0000 0001 0000 0010 0000 0000. Ergebnis ist 66048.

    Beispiel 3
    Lies 24 Bits aus {0, 0, 3}, also 0000 0000 0000 0000 0000 0011. Ergebnis ist 3.

    Beispiel 4
    Lies 10 Bits aus {202, 63}, also 1100 1010 0011 1111. Ergebnis ist 808 wegen 0011 0010 1000.


    Ich danke Euch. Das sollte es dann gewesen sein mit meinen Byte-Funktion-Fragen.

    Viele Grüße
    Bartosz
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    BitArray ist sicher eine ganz gute Variante.

    Ansonsten kann man das sicher auch in etwa so machen.

    C#-Quellcode

    1. var ints = new int[] { 1, 2, 0 };
    2. var str_ints = ints.Select(x => Convert.ToString(x, 2).PadLeft(8, '0'));
    3. var str = string.Join("", str_ints);
    4. var ul = Convert.ToUInt64(str, 2);
    5. ints = [202, 63] ;
    6. str_ints = ints.Select(x => Convert.ToString(x, 2).PadLeft(8, '0'));
    7. str = string.Join("", str_ints);
    8. var cnt = 10;
    9. ul = Convert.ToUInt64(str.Substring(0,cnt), 2);

    VB.NET-Quellcode

    1. Dim ints = New Integer() {1, 2, 0}
    2. Dim str_ints = ints.[Select](Function(x) Convert.ToString(x, 2).PadLeft(8, "0"c)).ToList()
    3. Dim str = String.Join("", str_ints)
    4. Dim ul = Convert.ToUInt64(str, 2)
    5. ints = _(202, 63)
    6. str_ints = ints.[Select](Function(x) Convert.ToString(x, 2).PadLeft(8, "0"c)).ToList()
    7. str = String.Join("", str_ints)
    8. Dim cnt = 10
    9. ul = Convert.ToUInt64(str.Substring(0, cnt), 2)


    Bei ganz grossen Zahlen kann man dann auch noch auf BigInteger ausweichen.

    Freundliche Grüsse

    exc-jdbi

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „exc-jdbi“ () aus folgendem Grund: Letztes Beispiel gar nicht richtig angeschaut

    @Haudruferzappeltnoch Bin mir nicht so sicher, ob es dasselbe Ziel ist. Jedenfalls erhalte ich mit deiner Funktion aus der letzten Frage andere Ergebnisse. Da stellt sich mir die Frage, ob die zu dem Zeitpunkt entstandene Lösung noch einen Fehler hat.
    Beispielgesuchtes Ergebnis aus dieser FrageErgebnis aus letzter FrageOk?
    Lies 16 Bits aus {1, 2}, also 0000 0001 0000 0010.
    2581
    Lies 24 Bits aus {1, 2, 0}, also 0000 0001 0000 0010 0000 0000.
    66048
    258
    Lies 24 Bits aus {0, 0, 3}, also 0000 0000 0000 0000 0000 0011.
    30
    Lies 10 Bits aus {202, 63}, also 1100 1010 0011 1111.
    808808

    Mit deiner alten Funktion klappte ja auch {3, 148} , Startposition = 7 und bitCount = 6. Ergebnis = 50. Da habe ich nicht viel anders getestet.

    Viele Grüße
    Bartosz

    Neu

    Ich habe ein ähnliches Problem, ich hoffe es passt hier halbwegs.

    Ich habe folgende Datei:

    Ich möchte hierbei die Offsets 31C und 31D auslesen, was mit diesem Code auch klappt:

    VB.NET-Quellcode

    1. ​Dim loadMemY1(3) As Byte
    2. Dim loadMemY2(3) As Byte
    3. Dim YCoordinate As String
    4. Dim fileOpen As IO.FileStream = IO.File.Open(strFileName, IO.FileMode.Open)
    5. fileOpen.Seek(&H31D, IO.SeekOrigin.Begin)
    6. fileOpen.Read(loadMemY1, 0, 1)
    7. fileOpen.Seek(&H31C, IO.SeekOrigin.Begin)
    8. fileOpen.Read(loadMemY2, 0, 1)
    9. fileOpen.Close()

    Geprüft habe es hiermit:

    VB.NET-Quellcode

    1. MsgBox(System.Text.Encoding.UTF8.GetString(loadMemY1))
    2. MsgBox(System.Text.Encoding.UTF8.GetString(loadMemY2))


    Allerdings möchte ich keine Ausgabe des dekodierten Textes, sondern möchte erst Offsets 31D und 31C zunächst hintereinander zusammenfügen (ergibt hier 0258) und das dann in dezimal umrechnen (ergibt 600) und irgendwie ausgeben (als Label um genauer zu sein).
    Ich programmiere extrem selten und wenn, dann nur simple Dinge, die nichts mit HEX u.ä. zu tun haben. Das hier ist auch eine Ausnahme, weshalb ich mich hier nicht noch tief in die ganze Materie einarbeiten möchte (ich hab jetzt schon einen kleinen Knoten im Hirn :) ).
    Wie füge ich erstens beide Offsets zusammen? Normalerweise (mit Strings) würde ich das so machen, was hier allerdings nicht funktioniert:

    VB.NET-Quellcode

    1. ​Dim loadmemY As String
    2. loadmemY = loadMemY1 & loadMemY2

    Und wenn ich dann das Ergebnis (hier 0258) habe, wie rechne ich das dann in dezimal um? Umgekehrt ginge es vielleicht so:

    VB.NET-Quellcode

    1. strHex = Hex(loadmemY)

    Aber wie ginge das in meinem Fall?

    Neu

    @Coder Sieh Dir mal den 3. Parameter von fileOpen.Read() an.
    learn.microsoft.com/de-de/dotn…estream.read?view=net-8.0
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Neu

    Coder schrieb:

    Was stimmt an dem nicht?
    Diese Fragestellung.
    Wenn Du 2 Bytes ausliest statt 1 Byte und diese 2 Bytes in 1 UShort konvertierst, ist Dein Problem gelöst.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Neu

    @Haudruferzappeltnoch
    Danke dir, das scheint zu funktionieren!
    Problem war nämlich, dass die - wie eingangs beschrieben - in umgekehrter Reihenfolge ausgelesen werden mussten. Also:
    Offset 31D (02 im Screenshot) und Offset 31C (58 im Screenshot) zusammengesetzt werden mussten (-> 0258) und anschließen konvertiert (-> 600). Dass funktioniert nun. Danke nochmal! :)

    Neu

    Da Zahlen im LittleEndian-Format gespeichert werden, gehts ganz einfach.
    Testdat.txt im Anhang

    Consolen Tesrprogramm:

    VB.NET-Quellcode

    1. Module Module1
    2. Sub Main()
    3. Dim strFileName As String = "d:\testdat.txt"
    4. Dim loadMemY1(2) As Byte
    5. ' Dim YCoordinate As String
    6. Dim fileOpen As IO.FileStream = IO.File.Open(strFileName, IO.FileMode.Open)
    7. 'fileOpen.Seek(&H31C, IO.SeekOrigin.Begin)
    8. fileOpen.Seek(8, IO.SeekOrigin.Begin) 'zum testen mit testdat
    9. 'Inhalt testdat: 61 62 63 64 65 66 67 68 58 02 78 79 7A
    10. fileOpen.Read(loadMemY1, 0, 2)
    11. fileOpen.Close()
    12. Dim Zahl As UShort = BitConverter.ToUInt16(loadMemY1, 0)
    13. Debug.Print("Ergebnis: " & Zahl.ToString)
    14. End Sub
    15. End Module
    Dateien
    • testdat.txt

      (13 Byte, 7 mal heruntergeladen, zuletzt: )

    Neu

    Haudruferzappeltnoch schrieb:

    Nur wenn die Reihenfolge stimmt und die beiden Stellen in Folge sind.
    Ansonsten machst du:
    Dim ergebnis = CInt(LoadMemY1.First) << 8 Or CInt(LoadMemY2.First)

    Noch eine Frage: wie gehe ich hier vor, wenn es mehr als 2 Offsets sind, die in umgekehrter Reihenfolge ausgelesen und zusammengesetzt werden müssen?
    Z.B.
    Offset H505 = 05
    Offset H506 = 95
    Offset H507 = 7A
    Offset H508 = 35
    -> 35 7A 95 05
    Bonus: einmal Ausgabe als Hex (0x357A9505) und einmal dezimal.

    Neu

    Coder schrieb:

    Noch eine Frage:
    Packe die Werte in der richtigen Reihenfolge in ein Byte-Array und verwende BitConverter.To_WAS_AUCH_IMMER():
    learn.microsoft.com/de-de/dotn…ter?view=netframework-4.8
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Neu

    Danke, musste ein paar Modifikationen vornehmen und es scheint zu klappen. :)

    VB.NET-Quellcode

    1. Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    2. 'GeckoWebBrowser2.Navigate(TextBox1.Text)
    3. Dim strFileName As String = "D:\Downloads\Neuer Ordner\testdat2.txt"
    4. Dim loadMemY1(4) As Byte
    5. ' Dim YCoordinate As String
    6. Dim fileOpen As IO.FileStream = IO.File.Open(strFileName, IO.FileMode.Open)
    7. 'fileOpen.Seek(&H31C, IO.SeekOrigin.Begin)
    8. fileOpen.Seek(4, IO.SeekOrigin.Begin) 'zum testen mit testdat
    9. 'Inhalt testdat: 88 16 88 58 00 9C B7 01 58 02 FF FF 00
    10. fileOpen.Read(loadMemY1, 0, 4)
    11. fileOpen.Close()
    12. Dim Zahl As Integer = BitConverter.ToUInt32(loadMemY1, 0)
    13. MsgBox("Ergebnis: " & Zahl.ToString)
    14. End Sub

    Die Testdat habe ich ein wenig an meine Praxis angepasst, um es besser testen zu können.