Reverse Modulo Berechnung

  • C#
  • .NET (FX) 4.5–4.8

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von exc-jdbi.

    Reverse Modulo Berechnung

    Hey,

    Also, hatte schon mal so eine ähnliche Frage, hier nochmal mit einer kleinen Abwandlung.
    Gegeben sei ein Integer x zwischen 0 bis int.MaxValue - 1.
    Es gilt a und b zu finden, sodass a % b = x.
    a ist random, aber es muss gelten a > x.

    Die Ausgangsfrage a % b = x lässt sich umformulieren in a = n*b + x.
    Daraus folgt a - x = n*b bzw (a - x)/n = b.

    Ich möchte also für jede Zahl zwischen 0 und int.MaxValue - 1
    ein a und ein b finden sodass a % b = x gilt und auch das a und b beides ints sind, und keine longs.

    Habe folgendes auf die Beine gestellt, failed aber bei höheren Werten weil ich keine Teiler finde :c

    C#-Quellcode

    1. private static readonly Random Random = new Random();
    2. public static void Main(string[] args)
    3. {
    4. int number = 1337;
    5. var stuff = FindModulo(number);
    6. Console.WriteLine($"a = {stuff[0]}");
    7. Console.WriteLine($"b = {stuff[1]}");
    8. Console.WriteLine($"a%b = {stuff[0] % stuff[1]}");
    9. }
    10. public static int[] FindModulo(int target)
    11. {
    12. if (target < 0)
    13. throw new ArgumentOutOfRangeException(nameof(target));
    14. var a = 0;
    15. var b = 0;
    16. do
    17. {
    18. a = Random.Next(target + 1, int.MaxValue);
    19. int ax = a - target;
    20. var ds = GetFactors(ax).Where(x => x > target).ToArray();
    21. var dx = ds.ElementAt(Random.Next(1, ds.Length));
    22. b = ax / dx;
    23. } while (b < target);
    24. return new[] {a, b};
    25. }
    26. static IEnumerable<int> GetFactors(int n)
    27. {
    28. var pairList =
    29. from i in Enumerable.Range(1, (int) (Math.Round(Math.Sqrt(n) + 1)))
    30. where n % i == 0
    31. select new {A = i, B = n / i};
    32. foreach (var pair in pairList)
    33. {
    34. yield return pair.A;
    35. yield return pair.B;
    36. }
    37. }


    C# Developer
    Learning C++
    @Rikudo Nimm Dir einfach ein bekanntes Lösungs-Tuple und teste, wie Dein Algo mit den entsprechenden Input-Werten davon umgeht.
    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!
    Hallo @Rikudo

    (a - x)/n = b


    Meines erachtens muss trotzdem noch x % ggT(a,b) = 0 gelten.

    Damit das zügig lauft, also auch für die grösseren Zahlen, wirst du nicht um den EEA kommen.


    Edit: Korrigiert: x % ggT(a,b) = 0

    Freundliche Grüsse

    exc-jdbi

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „exc-jdbi“ ()

    Hallo @Rikudo

    Deine Umformung zu a = n*b + x sieht schon korrekt aus.

    Ich schreibe es nochmals anders hin, ist wahrscheinlich auf den ersten Blick verständlicher.
    Die Basis: (b + x) % b = x.
    Mit dieser Formel kann gearbeitet werden.

    Edit:
    Ich hab das jetzt nochmals kurz angeschaut, und wie ich feststellen konnte ist es sogar noch einfacher, als ich gestern abend vermutet hatte. Der EEA wird dafür nicht einmal gebraucht, und die oben erwähnte Bedingung habe ich auch nicht verwendet.

    Ganz einfacher und sehr schneller Code, ohne tief in die mathematischen Gegebenheiten zu gehen, und das auch für grosse r.

    Einzige Bedingung dir für r gilt: Int32.MaxValue - r > r, und deine Bedingung a > r.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Option Strict On
    2. Option Explicit On
    3. 'Vorgabe: a > r
    4. 'Basis: (r + m) % m = r
    5. 'Bedingung: MaxValue - r > r
    6. 'Formel heisst a % m = r
    7. 'Formel Basis (r + m) % m = r
    8. Public Module Module1
    9. Private rand As New Random
    10. Public Sub Main()
    11. Dim mv = Int32.MaxValue
    12. Dim cnt As Int32 = 100000
    13. Dim r, idx, res() As Int32
    14. Dim lst As New List(Of Int32())
    15. idx = -1
    16. For i As Int32 = 0 To cnt - 1
    17. idx += 1
    18. Do
    19. r = rand.Next(mv)
    20. Loop While mv - r < r
    21. res = XModSolve(r)
    22. 'res return a, m, r
    23. If res IsNot Nothing Then
    24. lst.Add(res)
    25. End If
    26. Next
    27. Stop
    28. End Sub
    29. Private Function XModSolve(ByVal r As Int32) As Int32()
    30. 'Formel heisst (r + m) % m = r
    31. If r >= 0 Then
    32. Dim a, m As Int32
    33. Dim mv = Int32.MaxValue
    34. If mv - r < r Then
    35. Throw New ArgumentException("MaxValue - r must be greater then r")
    36. End If
    37. While True
    38. a = rand.Next(r, mv)
    39. m = a - r
    40. If m < 0 Then Continue While
    41. If m < r Then Continue While
    42. If Not a > r Then Continue While
    43. If a Mod m = r Then Exit While
    44. End While
    45. Return {a, m, r}
    46. End If
    47. Return Nothing
    48. End Function
    49. End Module


    Schöner Feierabend ins Wocheende wünsche ich.

    Freundliche Grüsse

    exc-jdbi

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „exc-jdbi“ ()

    Ich hab bis jetzt noch keine konkrete Lösung gefunden, für den restlichen Bereich.

    Das Problem ist das durch die obige Formel alle 3 Variablen a,m,r im Verhältnis stehen. Nimmt man eine Zahl im obigen Bereich versagt die Formel (r + m) % m = r.

    Es ist mir bis jetzt nicht bekannt, das dies möglich ist, muss aber auch zugeben, dass ich mich nicht sehr tief damit befasst habe.

    Freundliche Grüsse

    exc-jdbi