Box Bit Rotate

  • C#
  • .NET (FX) 1.0–2.0

Es gibt 12 Antworten in diesem Thema. Der letzte Beitrag () ist von Narretei.

    Box Bit Rotate

    Hey
    Wer mich kennt weiß das ich gerne mit bit operationen rumspiele :D Auch jetzt probiere ich wieder etwas lustiges aus.
    Ich möchte zwei bytes boxweise rotieren, sowohl gegen als auch im Uhrzeigersinn.
    Hier ein Bild zur Erklärung:



    Ich bin mir noch nicht ganz sicher wie ich das am besten Anstelle.
    Bspw, gehen wir davon aus das ich gegen den Uhrzeigersinn rotieren möchte.
    Ich würde alle bits im oberen byte nach links schieben. Das byte links müsste ich mir merken. Aber wie kann ich mir
    die Position jedes alten bytes merken ohne ewig viele Variablen anzulegen. hat jemand einen Denkanstoß?

    EDIT: Ich habe es geschafft eine Box (die ganz links) erfolgreich zu rotaten, allerdings ist mein Code sehr umständlich, und ich bin mir sicher das man sowas elegant in einem 2-zeiler oder so lösen kann.
    Außerdem habe ich noch keinen Plan wie man das auf die anderen boxen anwendet ohne jedes Bit manuell zu testen und neu zu setzen...

    Quellcode

    1. public static void Main(string[] args)
    2. {
    3. byte a = 123; // 0111 1011
    4. byte b = 234; // 1110 1010
    5. Console.WriteLine(Convert.ToString(a, 2));
    6. Console.WriteLine(Convert.ToString(b, 2));
    7. BoxFlip(a, b);
    8. Console.ReadKey();
    9. }
    10. private static void BoxFlip(byte a, byte b)
    11. {
    12. // Process last box, check what bits are set;
    13. bool topleft = (a & (1 << 7)) != 0;
    14. bool bottomleft = (b & (1 << 7)) != 0;
    15. bool bottomright = (b & (1 << 6)) != 0;
    16. bool topright = (a & (1 << 6)) != 0;
    17. // Set bits in last box to 0
    18. a &= 0b00111111;
    19. b &= 0b00111111;
    20. // Update topleft
    21. if (topright)
    22. {
    23. a |= (1 << 7);
    24. }
    25. else
    26. {
    27. a = (byte) (a & (~(1 << 7)));
    28. }
    29. // Update bottomleft
    30. if (topleft)
    31. {
    32. b |= (1 << 7);
    33. }
    34. else
    35. {
    36. b = (byte) (b & (~(1 << 7)));
    37. }
    38. // Update bottomright
    39. if (bottomleft)
    40. {
    41. b |= (1 << 6);
    42. }
    43. else
    44. {
    45. b = (byte) (b & (~(1 << 6)));
    46. }
    47. // Update topright
    48. if (bottomright)
    49. {
    50. a |= (1 << 6);
    51. }
    52. else
    53. {
    54. a = (byte) (a & (~(1 << 6)));
    55. }
    56. Console.WriteLine("Last Box Rotated:");
    57. Console.WriteLine(Convert.ToString(a, 2));
    58. Console.WriteLine(Convert.ToString(b, 2));
    59. }
    60. }
    C# Developer
    Learning C++

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Rikudo“ ()

    Aufs Risiko, dass irgend einen total offensichtlichen und peinlichen Fehler mache und erst morgen nach der Arbeit dazu komme, ihn zu korrigieren:

    VB.NET-Quellcode

    1. Dim A As Byte = 0b10111001 'B9
    2. Dim B As Byte = 0b01101101 '6D
    3. Dim ALeft = A And 0b10101010 'AA
    4. Dim ARight = A And 0b01010101 '55
    5. Dim BLeft = B And 0b10101010 'AA
    6. Dim BRight = B And 0b01010101 '55
    7. Dim NewA = (ARight << 1) Or BRight
    8. Dim NewB = ALeft Or (BLeft >> 1)

    Ich tu jetzt einfach mal so, als hätte VB binäre Zahlenliterale mit "0b" am Anfang, weil ich zu faul bin, die Umrechnung zu Hexadezimal (mit "&H" am Anfang) im Kopf zu machen. Ich hab aber dazukommentiert, was ich glaube, dass die richtigen Werte sind.
    Der Code ist ungetestet.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    @Rikudo Ich würde die 4 Rotationszentren allein behandeln, da kannst Du sogar ne separate Klasse für machen.
    Das Shiften selbst machst Du dann schön und verständlich mit ner List(Of Char) oder schnell und pflegeunfreundlich mit << bzw. >>.
    Als Output zwei Strings, die obere und die untere Zeile, die setzt Du dann mit denen der anderen Objekte zusammen und feddich.
    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!
    @Rikudo Natürlich kann man.
    Aber hast Du noch den Überblick?
    Was, wenn Du 128-Bit-Zahlen rotieren lassen willst? Meine Lösung ist beliebig kaskadierbar.
    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!
    Man kann auch einfach mit der BitArray-Klasse hantieren.

    VB.NET-Quellcode

    1. Option Strict On
    2. Public Class Form1
    3. Private r As New Random
    4. Private b1 As Byte = CByte(r.Next(0, 256))
    5. Private b2 As Byte = CByte(r.Next(0, 256))
    6. Private Sub BoxRotate(ByVal rotatePosition As Integer, ByVal aroundTheClock As Boolean)
    7. If rotatePosition < 1 OrElse rotatePosition > 7 Then
    8. Throw New Exception("Value must be in Range from 1 to 7")
    9. End If
    10. Dim ba1 As New BitArray(8, False)
    11. Dim ba2 As New BitArray(8, False)
    12. For i = 0 To 7
    13. ba1.Set(i, (b1 And (1 << i)) <> 0)
    14. ba2.Set(i, (b2 And (1 << i)) <> 0)
    15. Next
    16. Dim tmp As Boolean = ba1.Get(rotatePosition - 1)
    17. If aroundTheClock Then
    18. ba1.Set(rotatePosition - 1, ba1.Get(rotatePosition))
    19. ba1.Set(rotatePosition, ba2.Get(rotatePosition))
    20. ba2.Set(rotatePosition, ba2.Get(rotatePosition - 1))
    21. ba2.Set(rotatePosition - 1, tmp)
    22. Else
    23. ba1.Set(rotatePosition - 1, ba2.Get(rotatePosition - 1))
    24. ba2.Set(rotatePosition - 1, ba2.Get(rotatePosition))
    25. ba2.Set(rotatePosition, ba1.Get(rotatePosition))
    26. ba1.Set(rotatePosition, tmp)
    27. End If
    28. Dim res(1) As Byte
    29. ba1.CopyTo(res, 0)
    30. ba2.CopyTo(res, 1)
    31. b1 = res(0)
    32. b2 = res(1)
    33. ShowResult()
    34. End Sub
    35. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    36. BoxRotate(TrackBar1.Value, False)
    37. End Sub
    38. Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
    39. BoxRotate(TrackBar1.Value, True)
    40. End Sub
    41. Private Sub ShowResult()
    42. For i = 7 To 0 Step -1
    43. Console.Write(CInt((b1 And (1 << i)) <> 0) * -1)
    44. Next
    45. Console.Write(vbNewLine)
    46. For i = 7 To 0 Step -1
    47. Console.Write(CInt((b2 And (1 << i)) <> 0) * -1)
    48. Next
    49. Console.Write(vbNewLine)
    50. Console.Write(vbNewLine)
    51. End Sub
    52. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    53. ShowResult()
    54. End Sub
    55. End Class
    Cloud Computer? Nein Danke! Das ist nur ein weiterer Schritt zur totalen Überwachung.
    „Wer die Freiheit aufgibt, um Sicherheit zu gewinnen, wird am Ende beides verlieren.“
    Benjamin Franklin

    NoIde schrieb:

    VB.NET-Quellcode

    1. Console.Write(CInt((b1 And (1 << i)) <> 0) * -1)
    machst Du

    VB.NET-Quellcode

    1. Console.Write(-CInt((b1 And (1 << i)) <> 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!

    Bluespide schrieb:

    byte rotA = ((a And 0b01010101) << 1) Or (b And 0b01010101)
    Byte rotB = ((b And 0b10101010) >> 1) Or (a And 0b10101010)

    ? Ich bin gerade am Handy und kann das leider nicht testen, geht das? (In Rikudos Funktion)


    Ja das funktioniert! Habs mal in C# umgeschrieben:

    C#-Quellcode

    1. ​public static void Main(string[] args)
    2. {
    3. byte a = 123; // 0111 1011
    4. byte b = 234; // 1110 1010
    5. Console.WriteLine(Convert.ToString(a, 2));
    6. Console.WriteLine(Convert.ToString(b, 2));
    7. byte rotA = (byte) (((a & 0b01010101) << 1) | (b & 0b01010101));
    8. byte rotB = (byte) (((b & 0b10101010) >> 1) | (a & 0b10101010));
    9. Console.WriteLine(Convert.ToString(rotA, 2)); //1110 0010
    10. Console.WriteLine(Convert.ToString(rotB, 2)); //0111 1111
    11. }


    @Bluespide ist es auch möglich mit so einem Trick die rotationsrichtung zu ändern? Also von counter clockwise zu clockwise bspw.
    C# Developer
    Learning C++

    Rikudo schrieb:

    die rotationsrichtung zu ändern?
    Probierma statt << 1 ==> * 2
    und statt >> 1 ==> * 0.5.
    Da übergibst Du den Faktor, musst aber das ganze in Double machen, wegen den gebrochenen Faktoren.
    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!
    Mach dies:

    C#-Quellcode

    1. rotA = (byte)(((a & 0x55) << 1) | (b & 0x55));
    2. rotB = (byte)(((b & 0xaa) >> 1) | (a & 0xaa));

    zu das:

    C#-Quellcode

    1. rotA = (byte)(((a & 0xaa) >> 1) | (b & 0xaa));
    2. rotB = (byte)(((b & 0x55) << 1) | (a & 0x55));
    Cloud Computer? Nein Danke! Das ist nur ein weiterer Schritt zur totalen Überwachung.
    „Wer die Freiheit aufgibt, um Sicherheit zu gewinnen, wird am Ende beides verlieren.“
    Benjamin Franklin

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „NoIde“ ()

    @Rikudo Musste noch mal ran an den Code, jetzt funktioniert es, bin falsch da ran gegangen. Ging sogar nochmal kürzer.

    Hier nun links und rechts herum, nur an angegebener Stelle, ohne BitArray. Also rotatePosition muss 1 - 7 sein!

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private r As New Random
    3. Private a As Byte = CByte(r.Next(0, 256))
    4. Private b As Byte = CByte(r.Next(0, 256))
    5. Private Sub BoxRotate(ByVal rotatePosition As Integer, ByVal aroundTheClock As Boolean)
    6. Dim aa, bb, p1, p2 As Byte
    7. p1 = CByte(&H1 << rotatePosition)
    8. p2 = p1 >> 1
    9. If aroundTheClock Then
    10. aa = (a And p1) >> 1 Or (b And p1)
    11. bb = (b And p2) << 1 Or (a And p2)
    12. Else
    13. aa = (a And p2) << 1 Or (b And p2)
    14. bb = (b And p1) >> 1 Or (a And p1)
    15. End If
    16. Dim mask As Byte = CByte(&H3 << (rotatePosition - 1))
    17. a = a And Not mask Or aa
    18. b = b And Not mask Or bb
    19. ShowResult()
    20. End Sub
    21. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    22. BoxRotate(TrackBar1.Value, False)
    23. End Sub
    24. Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
    25. BoxRotate(TrackBar1.Value, True)
    26. End Sub
    27. Private Sub ShowResult()
    28. Dim res As String = ""
    29. For i = 7 To 0 Step -1
    30. res &= -CInt((a And (1 << i)) <> 0)
    31. Next
    32. res &= vbNewLine
    33. For i = 7 To 0 Step -1
    34. res &= -CInt((b And (1 << i)) <> 0)
    35. Next
    36. Label2.Text = res
    37. End Sub
    38. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    39. ShowResult()
    40. End Sub
    41. End Class
    Cloud Computer? Nein Danke! Das ist nur ein weiterer Schritt zur totalen Überwachung.
    „Wer die Freiheit aufgibt, um Sicherheit zu gewinnen, wird am Ende beides verlieren.“
    Benjamin Franklin

    Dieser Beitrag wurde bereits 9 mal editiert, zuletzt von „NoIde“ ()