For Next Schleifen lassen sich nicht ersetzen

  • VB.NET

Es gibt 13 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    For Next Schleifen lassen sich nicht ersetzen

    Ich habe ein kleines Programm geschrieben, welches den Zweck hat für das RSA Verschlüsselungsverfahren die Entstehung der Schlüsselpaare, welche man zur Ver und Entschlüsselung braucht, vorzuführen. Es funktioniert so, dass man 2 kleine Primzahlen in den ersten beiden Textboxen eingibt und dann auf den Button 1 drückt. Dann wird einem eine Liste von 30 Zahlen vorgeschlagen, die sich dafür eignen, als Verschlüsselungsexponent „ e „ verwendet zu werden. Wenn man sich für ein „ e „ entschieden hat, gibt man dieses in die 3te Textbox ein und denkt sich dann eine Zahl aus, die man verschlüsseln will und gibt diese in die 4 te
    Textbox ein. Wenn man dann auf den Button 2 drückt wird einem der Entschlüsselungsexponent „ d „ berechnet. Leider funktioniert das Programm nur mit sehr kleinen Primzahlen, die nicht
    größer als 100 sein sollten, wenn die Berechnung nicht zu lange dauern soll. Eine Idee, die ich hätte, um die Berechnungen unter dem Button 2 etwas zu beschleunigen, wäre eine andere Konstruktion der Doppelschleife. Anstatt von 2 For Next Schleifen würde ich lieber eine Do Loop Anweisung mit until oder while Bedingung benutzen, um die 2 Variablen zu berechnen. Mein Versuch die Schleifen :

    VB.NET-Quellcode

    1. For i = 1 To Y
    2. For x = 1 To Y
    3. Erg = i * R - x * P
    4. If Erg = EUCLID_RECURSIVE(P, R) Then
    5. d = i
    6. k = -1 * x
    7. Ausg= Ausg & CStr(i)& "mal "& CStr(R)& "minus "& CStr(x)& "mal "& CStr(P)& "= "&CStr(EUCLID_RECURSIVE(P,R)) & Chr(13)
    8. End If
    9. Next
    10. Next

    Zu ersetzen durch

    VB.NET-Quellcode

    1. Bo = False
    2. x= 0
    3. i= 0
    4. Do
    5. x= x + 1
    6. i = i + 1
    7. Erg = i * R - x * P
    8. If Erg = EUCLID_RECURSIVE(P, R) Then
    9. d= i
    10. k= -1 * x
    11. Bo = True
    12. Ausg= Ausg & CStr(i)& "mal "& CStr(R)& "minus "& CStr(x)& "mal "& CStr(P)& "= "&CStr(EUCLID_RECURSIVE(P,R)) & Chr(13)
    13. End If
    14. Loop Until Bo = True

    schlägt fehl.
    Laut dem Link : Do...Loop-Anweisung - Visual Basic | Microsoft Docs ist es egal, wie ich die Until Schleife aufbaue, ob das Until oder while am Kopf oder am Ende der Schleife steht.
    Es macht auch keinen Unterschied ob ich x = x+1 und i= i +1 oder ob ich x+= 1 und i += 1 schreibe, es funktioniert nicht. Unter dem Link :Geschachtelte Steuerungsstrukturen - Visual Basic | Microsoft Docs gibt es auch nur ein Beispiel für 2 verschachtelte For Next Schleifen, aber nicht für eine verschachtelte Do until Loop Konstruktion. Kann es sein, dass es in Visual Basic gar nicht möglich ist, das zu konstruieren ? Hier ist nochmal der komplette Programmcode :

    VB.NET-Quellcode

    1. Public Class Form1
    2. Public a, b, R, c, m, pot As Integer
    3. Public P As ULong
    4. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    5. Dim P, N, Z, x As Integer
    6. Dim moeg As String
    7. Dim Zeit1, Zeit2 As Date
    8. Dim Unterschied As Long
    9. Zeit1 = DateAndTime.Now
    10. x = 0
    11. moeg = " "
    12. P = (a - 1) * (b - 1)
    13. N = a * b
    14. For Z = 1 To P
    15. If EUCLID_RECURSIVE(P, Z) = 1 And x < 30 Then
    16. x = x + 1
    17. moeg = moeg & " Der ggT von Phi( N) : " & P & " und e : " & Z & " = " & EUCLID_RECURSIVE(P, Z) & Chr(13)
    18. End If
    19. Next
    20. Zeit2 = DateAndTime.Now
    21. Unterschied = DateAndTime.DateDiff(DateInterval.Second, Zeit1, Zeit2)
    22. Label1.Text = "RSA Modul: N = p mal q = " & a & " mal " & b & " = " & N & Chr(13) _
    23. & " Phi (n) = (P-1) mal (q-1) = " & "(" & a & "-1) * (" & b & "-1) = " & P & Chr(13) _
    24. & " Wähle eine zu Phi (N) teilerfremde Zahl e , für die gilt 1 < e < Phi(N)" & Chr(13) _
    25. & " Ausserdem gilt das der ggt von e und Phi(N) = 1 hier sind ein par Vorschläge für mögliche e" & Chr(13) & moeg & Chr(13) _
    26. & " wählen sie nun ein e aus der Liste aus und geben es in das 3te Eingabefeld ein, dazu denken sie sich bitte eine Zahl aus," & Chr(13) _
    27. & " die sie verschlüsseln wollen und geben diese in das 4 te Eingabefeld ein und drücken auf den Button 2 " & Chr(13) _
    28. & " Die Rechenzeit für die Erstellung der Liste der möglichen e hat : " & Unterschied & " Sekunden betragen"
    29. End Sub
    30. Private Sub TextBox1_TextChanged(sender As Object, e As EventArgs) Handles TextBox1.TextChanged
    31. If IsNumeric(TextBox1.Text) = True Then
    32. a = CInt(TextBox1.Text)
    33. End If
    34. End Sub
    35. Private Sub TextBox2_TextChanged(sender As Object, e As EventArgs) Handles TextBox2.TextChanged
    36. If IsNumeric(TextBox2.Text) = True Then
    37. b = CInt(TextBox2.Text)
    38. End If
    39. End Sub
    40. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    41. Dim i, x, Y, k, d, N, KL1, KL2, C1, C2 As Integer
    42. Dim Ausg As String
    43. Dim Erg, P As Long
    44. 'Dim Bo As Boolean
    45. Dim Zeit1, Zeit2 As Date
    46. Dim Unterschied As Long
    47. Zeit1 = DateAndTime.Now
    48. N = a * b
    49. P = (a - 1) * (b - 1)
    50. If P > R Then
    51. Y = P
    52. Else
    53. Y = R
    54. End If
    55. Ausg = ""
    56. 'Bo = False
    57. 'x = 0
    58. 'i = 0
    59. 'Do
    60. 'x = x + 1
    61. 'i = i + 1
    62. For i = 1 To Y
    63. For x = 1 To Y
    64. Erg = i * R - x * P
    65. If Erg = EUCLID_RECURSIVE(P, R) Then
    66. d = i
    67. k = -1 * x
    68. 'Bo = True
    69. Ausg = Ausg & CStr(i) & " mal " & CStr(R) & " minus " & CStr(x) & " mal " & CStr(P) & " = " _
    70. & CStr(EUCLID_RECURSIVE(P, R)) & Chr(13)
    71. End If
    72. 'Loop Until Bo = True
    73. Next
    74. Next
    75. KL1 = m Mod a
    76. KL2 = m Mod b
    77. C1 = ModbermitPotenz(KL1, R, a)
    78. C2 = ModbermitPotenz(KL2, R, b)
    79. c = China(C1, a, C2, b) Mod N
    80. Zeit2 = DateAndTime.Now
    81. Unterschied = DateAndTime.DateDiff(DateInterval.Second, Zeit1, Zeit2)
    82. Label5.Text =
    83. " Es beginnt die Berechnung der Inversen zu e modulo Phi(N), es gilt :" & Chr(13) _
    84. & " d mal e + k mal Phi(N) = 1 " & Chr(13) & Ausg & Chr(13) & "daraus folgt das d = " & d & " und k = " & k & Chr(13) _
    85. & " Um eine Nachricht m zu verschlüsseln, verwendet der Absender die Formel C= m hoch e mod N und erhält so aus der Nachricht m den Geheimtext c , " & Chr(13) _
    86. & m & " Hoch " & R & " Mod " & N & "=" & c & " Das Chiffrat ist also " & c & Chr(13) &
    87. " Der Geheimtext c kann durch modulare Exponentiation wieder zum Klartext m entschlüsselt werden." & Chr(13) _
    88. & " Der Empfänger benutzt die Formel m = c hoch d mod N mit dem nur ihm bekannten Wert d sowie N. " & Chr(13) _
    89. & c & " hoch " & d & " mod " & N & "= " & m & " Der Klartext ist also " & m & Chr(13) _
    90. & " Die Rechenzeit hat : " & Unterschied & " Sekunden betragen" & Chr(13)
    91. End Sub
    92. Private Sub TextBox4_TextChanged(sender As Object, e As EventArgs) Handles TextBox4.TextChanged
    93. If IsNumeric(TextBox4.Text) = True Then
    94. m = CInt(TextBox4.Text)
    95. End If
    96. End Sub
    97. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    98. Label2.Text = " Ein Rechner für das Testen von 2 Primzahlen siehe :https://de.wikipedia.org/wiki/RSA-Kryptosystem
    99. Geben sie nun die beiden Primzahlen ein und drücken auf den Button 1
    100. Primzahl1 Primzahl2 "
    101. Label3.Text = " hier das e eingeben"
    102. Label4.Text = " hier kommt eine Zahl hin
    103. die verschlüsselt werden soll"
    104. End Sub
    105. Private Sub TextBox3_TextChanged(sender As Object, e As EventArgs) Handles TextBox3.TextChanged
    106. If IsNumeric(TextBox3.Text) = True Then
    107. R = CInt(TextBox3.Text)
    108. End If
    109. End Sub
    110. Function EUCLID_RECURSIVE(P, R) 'Unterprogramm zur Anwendung des euklidische Algorithmus
    111. ' von daher zur Berechnung des größten gemeinsamen Teilers zweier natürlicher Zahlen
    112. Dim Ergebnis As Integer
    113. If R = 0 Then
    114. Ergebnis = P
    115. Else
    116. Ergebnis = EUCLID_RECURSIVE(R, P Mod R)
    117. End If
    118. EUCLID_RECURSIVE = Ergebnis
    119. End Function
    120. Function ModbermitPotenz(m, pot, N) 'Unterprogramm zur Ausführung von Mod Berechnungen für Zahlen mit Potenzen
    121. Static x, y, Z As Integer
    122. Static Produkt(pot + 10) 'Feld anlegen
    123. Produkt(0) = m 'initialisieren
    124. For x = 0 To pot
    125. y = (Produkt(x) * m)
    126. Z = y Mod N
    127. Produkt(x + 1) = Z
    128. Next
    129. Return Produkt(pot - 1)
    130. End Function
    131. Function China(a1, m1, a2, m2) 'Unterprogramm zur Anwendung des chinesischen Restsatz mit 2 Kongruenzen
    132. Static INV1, INV2, x, y, w, z, Erg
    133. Do
    134. INV1 = INV1 + 1
    135. x = m2 * INV1
    136. y = x Mod m1
    137. Loop Until (y = 1)
    138. Do
    139. INV2 = INV2 + 1
    140. w = m1 * INV2
    141. z = w Mod m2
    142. Loop Until (z = 1)
    143. Erg = (a1 * m2 * INV1) + (a2 * m1 * INV2)
    144. China = Erg
    145. End Function
    146. End Class
    Ich denke dass die Until oder While Schleife deshalb schneller ein Ergebnis liefert, weil sie sobald sie das Ergebnis gefunden hat,
    aufhört zu rechnen, während die For Next Schleife auch nachdem sie das Ergebnis gefunden hat weiterrechnen muss, bis der der Zählerstand erreicht ist, den ich im Kopf der Schleife angegeben habe.

    loosm schrieb:

    weiterrechnen muss, bis der der Zählerstand erreicht ist
    Sieh Dir mal den Befewhl Exit For an:
    docs.microsoft.com/de-de/dotne…statements/exit-statement
    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!

    loosm schrieb:

    Microsoft Docs ist es egal, wie ich die Until Schleife aufbaue, ob das Until oder while am Kopf oder am Ende der Schleife steht.

    Na ja es ist schon ein Unterschied, ob ich einen Kopf- oder Fußgesteuterte Schleife habe. Bei einer Kopfgesteuteren Schleife wird vor dem Abarbeiten der Schleife geprüft, ob diese überhaupt genutzt werden muss. Bei einer Fußgesteuterten Schleife muss man mindestens einmal durch die Schleife durch.
    NB. Es ist doch schön, wenn man lesbare Namen vergibt. Siehe auch [VB.NET] Beispiele für guten und schlechten Code (Stil).
    Ich habe auch versucht mit Exit do die Schleife zu beenden :

    VB.NET-Quellcode

    1. x= 0
    2. i= 0
    3. Do
    4. x = x + 1
    5. i = i + 1
    6. Erg = i * R - x * P
    7. If Erg = EUCLID_RECURSIVE(P, R) Then
    8. d= i
    9. k= -1 * x
    10. Ausg= Ausg & CStr(i)& "mal "& CStr(R)& "minus "& CStr(x)& "mal "& CStr(P)& "= "
    11. _ &CStr(EUCLID_RECURSIVE(P, R)) & Chr(13)
    12. Exit Do
    13. End If
    14. Loop



    Es funktioniert nicht, natürlich stimmt es, dass es nicht grundsätzlich egal ist, ob eine Schleife Kopf oder Fußgesteuert ist.
    Es ist nur in Bezug auf die in meinem Programm genutzte Doppelschleife egal, wie ich die Until oder While Schleife aufbaue, weil nur eine For next Schleifenkonstruktion funktioniert.
    Oder ist das Problem, aus beiden For-Schleifen gleichzeitig rauszuspringen?
    Da müsste man was anderes anwenden als Exit For - es gibt verschiedene Möglichkeiten.
    • Manche Prinzipienreiter würden einen TryCatch akzeptieren, der mit Exit Try verlassen wird.
    • Andere Prinzipienreiter (wie ich etwa) würden gnadenlos Goto einsetzen, weil s'ist imo auch kein gutes Benehmen, einen TryCatch als Sprungmarke zu missbrauchen, nur weil Goto soooo böse ist.
    • Andere Code-Philosophen würden eine Extra-Bool-Variable einführen, die dann in jeder (äusseren) Runde abgeprüft wird (bäh!).
    • Man könnte die Doppelschleife auch in eine Methode packen, die beim Treffer dann returnt - dassis vielleicht noch der beste Ansatz.

    Aber bevor jetzt die Goto-Debatte losgeht, bitte erstmal abwarten, ob das Thema "verschachtelte Schleife verlassen" überhaupt das für den TE relevante Problem ist.
    Also TE, antworte: Ist dein Problem, aus einer verschachtelten For-Schleife komplett rauszuspringen?

    loosm schrieb:

    Es funktioniert nicht
    Die Schleife, die Du hier angegeben hast, wird korrekt verlassen.
    Überzeuge Dich davon, indem Du einen Haltepunkt darauf setzt und lerne zu debuggen:
    Debuggen, Fehler finden und beseitigen
    ====
    @FormFollowsFunction Wenn der TE dort ein Exit For hingeschrieben hat, wurde das von der Entwicklungsumgebung in ein Exit Do umgewandelt, weil nur das funktioniert.

    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!

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

    Hi @loosm

    Ich würde das was bereits funktioniert erstmal dabei belassen.

    Und mit Continue For das, was nicht abgearbeitet werden soll, damit überspringen.


    Hier eine grob geschätzte Lösung.

    VB.NET-Quellcode

    1. For i = 1 To Y
    2. For x = 1 To Y
    3. Erg = i * R - x * P
    4. If Erg <> EUCLID_RECURSIVE(P, R) Then '<- Achtung Prüfung negiert (Frage mal andersherum...)
    5. Continue For '<- Innere Schleife ab hier überspringen
    6. Else '<- Sonst-Zweig (wie gehabt abarbeiten ...)
    7. d = i
    8. k = -1 * x
    9. Ausg = Ausg & CStr(i) & "mal " & CStr(R) & "minus " & CStr(x) & "mal " & CStr(P) & "= " & CStr(EUCLID_RECURSIVE(P, R)) & Chr(13)
    10. End If
    11. Next
    12. Next


    Das geht auch mit While und Do.

    Hier der Link zur Dokumentation.

    Wie schon die Vorredner/-schreiber erwähnten, ist evtl. eine weitere Prüfung,
    ob die äußere Schleife auch verlassen werden muss,
    mit einer Wahrheitsvariable, die in der inneren Schleife gesetzt wird.

    Ich hoffe, das hilft ...

    Und esoterisch betrachtet ist die Wahrheitsvariable das Fundament der ausserschleiflichen Erfahrung eines angehenden Code-Gurus. :)


    c.u. Joshi und grüße aus Hot-Hambuarch
    @Joshi Da es nach dem If-End If nicht weiter geht, kannst Du das Else weglassen.
    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!
    Das
    Programm funktioniert, wenn man in der If Abfrage ein Exit For oder
    Continue For einsetzt. Ich kann aber leider nicht feststellen, ob das Programm dadurch die
    Schleife schneller verlässt und dadurch schneller rechnet.

    Getestet habe ich das mit der folgenden Zahlenkombination : Primzahlen : 113
    und 127 gewähltes e: 23 zu verschlüsselnde Zahl 7

    Die
    Messungen schwanken zwischen 200 und 300 Sekunden.

    Das
    mit dem Debuggen war ein guter Hinweis. Ich hatte das bisher nicht
    angewendet, weil ich bisher meine Fehler dadurch gefunden habe, dass
    ich VB Scripte geschrieben hatte.

    Mit der folgenden Zahlenkombination : Primzahlen : 3 und 5
    gewähltes e: 7 zu verschlüsselnde Zahl 2

    habe ich das Programm im Einzelschritt laufen lassen bei x = 8 und i= 8
    erscheint das Ergebnis mit oder ohne Exit For.

    Durch das Debuggen ist mir klar geworden, warum ich mit einer Do until
    Doppelschleife, niemals in der If Abfrage ankommen kann. Um das zu
    verdeutlichen habe ich ein kleines Script geschrieben.

    Visual Basic-Quellcode

    1. Dim i,x,String1,String2
    2. ' For next Zählschleifen
    3. String1 = " Mit For Next Schleife :" & Chr(13)
    4. For i=1 To 3
    5. For x=1 To 3
    6. String1 = String1 & " I : " & Cstr(i) & " X : " & Cstr(x) & chr(13)
    7. next
    8. next
    9. '----------------------------------------------------------------------
    10. ' Do Loop Schleife
    11. String2 = " Mit Do While Schleife :" & Chr(13)
    12. x=0
    13. i=0
    14. Do
    15. x=x+1
    16. i =i+1
    17. String2 = String2 & " I : " & Cstr(i) & " X : " & Cstr(x) & chr(13)
    18. Loop until (X >=3)And ((i) >=3)
    19. '---------------------------------------------------
    20. MsgBox String1 & String2

    loosm schrieb:

    Das
    Programm funktioniert, wenn man in der If Abfrage ein Exit For oder
    Continue For einsetzt. Ich kann aber leider nicht feststellen, ob das Programm dadurch die
    Schleife schneller verlässt und dadurch schneller rechnet.
    Das braucht man nicht prüfen - das ergibt sich aus den Gesetzen der Logik:
    Eine Schleife, die vorzeitig verlassen wird, ist immer schneller als dieselbe Schleife, wenn sie nicht vorzeitig verlassen wird.

    Es ist wie beim Busfahren: Die Fahrt ist schneller zuende, wenn du früher aussteigst.