Split in Bitshift Or

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

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von Rikudo.

    Split in Bitshift Or

    Hey Community,

    Hab mal wieder n ähnliches Problem wie vor kurzem.
    Diesmal muss ich eine gegeben Zahl in eine Or-Bitshift Operation zerlegen also in | in C# :D

    Angenommen ich habe 15 als Ausgangszahl kann man das Bspw in folgendes zerlegen:

    7 | 13 denn 7 | 13 = 15.

    Wie kann ich eine zufällige Kombination aus den möglichen finden bzw errechnen also quasi die werte a und b sodass a | b = Zahl?
    C# Developer
    Learning C++
    Hi
    nimm einfach eine Zufallszahl zwischen 0 und 15. Dann stelle dir vor, du hast folgendes:
    a | b | c = 15
    Wobei a | b = 15 gelten soll und c einfach ein zufälliger Wert ist. Die erste Zahl soll a sein, die zweite b | c. Jetzt wähle a und c als Zufallszahlen zwischen 0 und 15 und b als ~a. Somit ist Zahl eins eben a und Zahl zwei ~a | c.

    Viele Grüße
    ~blaze~

    Quellcode

    1. class Program
    2. {
    3. static void Main(string[] args)
    4. {
    5. int data = 560;
    6. int[] v = FindBitshiftOr(data);
    7. Console.WriteLine("{0} << {1} = {2}", v[0], v[1], v[0] | v[1]);
    8. Console.ReadKey();
    9. }
    10. private static Random r = new Random();
    11. private static int[] FindBitshiftOr(int value)
    12. {
    13. int[] d = new int[2];
    14. int a = r.Next(0, value);
    15. int c = r.Next(0, value);
    16. int b = ~a;
    17. d[0] = a;
    18. d[1] = b | c;
    19. return d;
    20. }
    21. }



    @blaze : Was mach ich falsch, da kommt immer -1 raus?!
    C# Developer
    Learning C++
    Eigentlich nur ~a. Für 15 wäre das:

    C#-Quellcode

    1. var random = new Random();
    2. int a = random.Next(0, 16);
    3. int b = (~a) & 0xf;
    4. int c = random.Next(0, 16);
    5. int left = a;
    6. int right = b | c;

    bzw. als schönere Funktion:

    C#-Quellcode

    1. public static Tuple<int, int> Foo(int digits)
    2. {
    3. if (digits < 0 || digits > 31)
    4. throw new ArgumentOutOfRangeException("digits");
    5. Random rnd = new Random();
    6. int maxmask = (1 << digits) - 1;
    7. int a = rnd.Next(maxmask);
    8. return new Tuple(a, (~a & maxmask) | rnd.Next(maxmask));
    9. }

    Die Funktion sollte man ggf. aber über uint laufen lassen, da das dann auch für digits = 32 möglich ist (und über unchecked), aber dazu bin ich jetzt mal zu faul. Das funktioniert halt nur für Zweierpotenzen.

    Der Sinn dahinter ist, dass als erstes eine feste Zahl a bestimmt wird. Damit gilt, dass a | x = 15, muss x so gewählt werden, dass alle Bits, die in a nicht gesetzt sind, gesetzt sind, d.h. a | x = 1111 (binär); wenn die Bedingung erfüllt ist, ist das hinreichend. Die restlichen Bits von x können beliebig sein, da beim bitweisen Oder ja mindestens eines der beiden Bits gesetzt sein muss, damit das zugehörige Bit im Ergebnis ebenfalls gesetzt ist. Somit ist (~a & maxmask) so gewählt, dass die hinreichende Bedingung erfüllt wird (klar, y | ~y = 1, wenn y = 0 oder y = 1, gilt). Für c sind die Bits folglich beliebig wählbar und damit wird einfach die hinreichende Eigenschaft festgelegt und die restlichen Bits zufällig gewählt (für c werden ALLE Bits zufällig gewählt, aber die Wahl ist irrelevant, weil die bits in b ja bereits gesetzt sind).

    Viele Grüße
    ~blaze~
    @blaze : Danke für die detaillierte Erklärung :)
    Ich habs jetzt so gelöst:

    C#-Quellcode

    1. private static int[] DetermineOr(int value)
    2. {
    3. if (value < 0) { throw new DivideByZeroException("Value can't be less than zero."); }
    4. int[] a = new int[2];
    5. int b = value;
    6. int c = rnd.Next(0, value);
    7. int d = b & c;
    8. int e = b & ~c;
    9. a[0] = d;
    10. a[1] = e;
    11. return a;
    12. }
    C# Developer
    Learning C++