Take Random Value

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

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

    Take Random Value

    Hi,
    Also ich habe folgende function:

    C#-Quellcode

    1. private static Random rnd = new Random();
    2. private static int[] FindRightShift(int value)
    3. {
    4. int[] arr = new int[2];
    5. for (int i = 1; i < int.MaxValue; i++)
    6. {
    7. int b;
    8. if (int.TryParse((Math.Log(i / value) / Math.Log(2)).ToString(), out b))
    9. {
    10. arr[0] = i;
    11. arr[1] = b;
    12. Console.WriteLine("{0} >> {1} = {2}", arr[0], arr[1], arr[0] >> arr[1]);
    13. return arr;
    14. }
    15. }
    16. return arr;
    17. }


    Die funzt auch, allerdings dauert es mehrere Minuten bis alle Kombinationen ausgegeben wurden.
    Wie kann ich eine zufällige Kombination für mein Input finden ohne von 0 bis int.maxvalue zu loopen?
    C# Developer
    Learning C++
    Mit if (int.TryParse((Math.Log(i / value) / Math.Log(2)).ToString(), out b)) prüfst du doch nur, ob i / value eine 2er-Potenz ist, oder? Dann wäre die Bedingung z.B. bei i == value erfüllt und du kannst dir die ganze Schleife sparen.

    Wenn ich die Aufgabe richtig interpretiere, suchst du a und b, so dass a >> b == value ist, richtig?
    Falls ja

    Wenn man von einem non-circular shift ausgeht (links wird mit Nullen aufgeführt),
    muss (AFAIK) a = (2**b) * value + y sein, mit (2**b) * value + y <= Int32.MaxValue und y < 2**b.

    Also:

    Quellcode

    1. b = 0, y = 0 --> a = 1*value + 0, a >> 0 = value
    2. b = 1, y = 0 --> a = 2*value + 0, a >> 1 = value
    3. b = 1, y = 1 --> a = 2*value + 1, a >> 1 = value
    4. b = 2, y = 0 --> a = 4*value + 0, a >> 2 = value
    5. b = 2, y = 1 --> a = 4*value + 1, a >> 2 = value
    6. b = 2, y = 2 --> a = 4*value + 2, a >> 2 = value
    7. b = 2, y = 3 --> a = 4*value + 3, a >> 2 = value
    8. b = 3, y = 0 --> a = 8*value + 0, a >> 3 = value
    9. ...
    10. b = 3, y = 7 --> a = 8*value + 7, a >> 3 = value
    11. b = 4, y = 0 --> a = 16*value + 0, a >> 4 = value
    12. ...

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „3daycliff“ () aus folgendem Grund: Typo...

    @Rikudo Beschreib mal mit Worten, nicht aber mit Code, was Dein Code machen soll.
    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 schrieb:

    Eigentlich das was
    ich möglicherweise nicht richtig verstanden habe und nun auch nicht beschreiben kann.

    RodFromGermany schrieb:

    Beschreib mal mit Worten, nicht aber mit Code, was Dein Code machen soll.
    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:
    Dann zieh doch einfach zwei zufällige Werte (b und y) welche die Bedingungen (2**b) * value <= Int32.MaxValue und y < 2**b erfüllen.

    Für die erste Bedingung nimmst du einfach irgendeine ganze positive Zahl aus dem Intervall [1, 31] und prüfst die erste Bedingung (Vorsicht wegen Überlauf; idealerweise suchst du vorher das most significant bit was gesetzt ist, dann kannst du dir die Überprüfung auch sparen).
    Für das y, ziehst du eine ganze nicht negative Zahl aus dem halboffenen Intervall [0, 2**b). Schon hast du dein Ergebnis...
    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!
    @3daycliff
    @RodFromGermany

    Also ich bin jetzt soweit mit Hilfe eines Freundes gekommen:

    C#-Quellcode

    1. private static Random R = new Random();
    2. private static void FindRightShift(int number)
    3. {
    4. int maxPower = (int)Math.Log(int.MaxValue, 2); // 30 -> max power to not exceed int.MaxValue
    5. int y = R.Next(1, maxPower + 1); // random valid power
    6. int sub = (int)Math.Pow(2, y);
    7. int x = number * sub; // WARNING: x > int.MaxValue causes chaos!
    8. Console.WriteLine("{0} >> {1} = {2}", x, y, x >> y);
    9. }


    Jetzt haben wir jedoch keine Idee mehr warum folgendes Problem auftritt:




    Das Problem ist das die Ergebnisse manchmal stimmen, manchmal nicht.
    Hat jemand eine Idee woran das liegt und wie man das beheben kann?
    Die Bedingung ist nach wie vor die selbe also das die Werte int.maxvalue nicht überschreiten dürfen.
    Würde mir sehr weiterhelfen :)
    C# Developer
    Learning C++

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

    Rikudo schrieb:

    Das Problem ist das die Ergebnisse manchmal stimmen, manchmal nicht.
    Wie äußert sich das?
    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 schrieb:

    aber an der Ausgabe sehe ich ja das die Werte manchmal nicht stimmen
    Ich nicht.
    Poste bitte mal ein Beispiel mit dem falschen und korrekten Ergebnis.
    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!
    @RodFromGermany :

    Hier sieht man das doch :D (Rot Umrahmt == falsch)



    Als Input für die Funktion aus Post 11 gebe ich meine Ausgangszahl.
    Die Funktion berechnet jetzt zwei Zahlen a und b, sodass a >> b == meine Zahl.

    Im BIld : Die erste Zahl war -10, die Funktion hat mir aber ne Ko0mbi zurückgegeben die 6 ergibt -> falsch. Es muss ja logischerweiße wieder die Ausgangszahl -10 sein.
    Die zweite und die Dritte Zahl sind wieder korrekt, da das ergebnis das gleiche wie die Input-Zahl ist. Die nächste Zahl ist wieder falsch... usw.

    Manchmal stimmen die Ergebnisse manchmal nicht, und ich weiß nicht wieso.
    Irgendwo ist n kleienr Bug in der Funktion und den gilt es zu finden und zu beheben ^^
    C# Developer
    Learning C++
    @Rikudo OK.
    Wenn Du shiftest und fehler finden willst, solltest Du Dir das Binärmuster ansehen:

    VB.NET-Quellcode

    1. Dim value = 11
    2. Dim txt = Convert.ToString(value, 2)
    3. MessageBox.Show(txt)
    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!

    C#-Quellcode

    1. private static void Main()
    2. {
    3. FindShift(-10);
    4. FindShift(123);
    5. FindShift(66);
    6. FindShift(7999735);
    7. FindShift(678);
    8. FindShift(9000000);
    9. FindShift(789);
    10. FindShift(0);
    11. Console.ReadLine();
    12. }
    13. private static void FindShift(int pResult)
    14. {
    15. if (pResult == 0)
    16. {
    17. Console.WriteLine("0 >> 0 = 0");
    18. return;
    19. }
    20. int lIterations = (int)Math.Log(int.MaxValue / Math.Abs(pResult), 2);
    21. int lResult = (int)(pResult * Math.Pow(2, lIterations));
    22. Console.WriteLine(lResult + " >> " + lIterations + " = " + pResult);
    23. }


    Die gehen btw immer bis kurz vor int.maxvalue.
    wenn du's zufällig haben willst, einfach random objekt erstellen und die Zeile:
    (int)Math.Log(int.MaxValue / Math.Abs(pResult), 2)
    als Maximum nehmen (von 0 bis obiges)
    graphics.stanford.edu/~seander…ks.html#IntegerLogObvious
    Dürfte das ganze schneller machen, keine casts von Double->Int und außerdem muss man dann auch nichts mehr durch den Random int teilen. Man kann btw. auch gleich den Zähler auf 32 setzen und dann dekrementieren, dann bekommt man direkt die stelle von hinten und erhält die Info, wie weit man shiften darf. Dann nur noch Random zwischen 1 und dem erhaltenen Wert und um diesen nach links shiften, nach rechts muss dann natürlich eben jene Zahl wieder um den erhaltenen Random Wert geshiftet werden. Die komplizierteste Operation dabei ist die Schleife, welche dann maximal 32 mal durchlaufen wird, also in so ziemlich jedem Fall schneller als Division, geschweige denn Logarithmus.
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---