Bildverhältnis mittels größten gemeinsamen Teilers mittels Euklid'schem Algorithmus

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 5 Antworten in diesem Thema. Der letzte Beitrag () ist von Yanbel.

    Bildverhältnis mittels größten gemeinsamen Teilers mittels Euklid'schem Algorithmus

    Hallo liebes Forum,

    ich mache gerade einen Review über Code, der etwa ein Jahr alt ist. Ich habe ein bestimmtes Bild und wollte daraus das Bildverhältnis bestimmen.
    Also 1280 × 960 gehen in die Function rein und ein String 4:3 wird zurückgegeben.

    Der Code funktioniert, nur meine Frage ist, ob wir bitte die Funktion zusammen optimieren könnten. Zu der Zeit konnte ich noch nicht so programmieren wie heute. Daher der Post. Es braucht bestimmt keine 100 UInts...
    Falls jemand den Euklidschen Algor. nicht kennt, klickt hier. Eine andere Lösung wäre natürlich auch gut.

    Der Aufruf:

    VB.NET-Quellcode

    1. Label_Verhaeltnis.Text = GgT(CUInt(temp_Bitmap.Size.Width), CUInt(temp_Bitmap.Size.Height))


    Die Funktion:

    VB.NET-Quellcode

    1. Function GgT(ByVal Zaehler As UInteger, ByVal Nenner As UInteger) As String 'Euklid'scher Algorithmus (naja..)
    2. Dim a As UInteger = Zaehler
    3. Dim b(99) As UInteger
    4. b(1) = Nenner
    5. Dim _Rest(99) As UInteger '100 Werte
    6. For XYZ As Integer = 0 To 99
    7. _Rest(XYZ) = 10
    8. Next
    9. Dim Ausgabe As String
    10. Dim Verhaeltnis_Teil1 As UInteger
    11. Dim Verhaeltnis_Teil2 As UInteger
    12. Dim i As Integer = 1
    13. If i = 1 Then
    14. _Rest(1) = a Mod b(1)
    15. End If
    16. i += 1
    17. While i <= 99
    18. _Rest(i) = b(i - 1) Mod _Rest(i - 1)
    19. If (_Rest(i) = 0) Then
    20. Exit While
    21. End If
    22. If i > 1 Then 'immer (außer beim ersten Mal) b neu zuweisen
    23. b(i) = _Rest(i - 1)
    24. End If
    25. i += 1
    26. End While
    27. b(i) = _Rest(i - 1) 'b noch einmal zuweisen
    28. If i = 99 Then 'nur für den Fall, dass er zu lange braucht
    29. Return ""
    30. End If
    31. Verhaeltnis_Teil1 = CUInt(Zaehler / b(i))
    32. Verhaeltnis_Teil2 = CUInt(Nenner / b(i))
    33. Ausgabe = If(Verhaeltnis_Teil1 = 7 And Verhaeltnis_Teil2 = 3,
    34. "2,333 : 1 (Kino)",
    35. Verhaeltnis_Teil1.ToString + ":" + Verhaeltnis_Teil2.ToString)
    36. Return Ausgabe

    An die Neulinge: Nutzt Option Strict On und Option Infer Off. Dadurch kommt ihr mit Datentypumwandlungen nicht durcheinander und der Code verbessert sich um Einiges! Solche Fehler à la Dim Beispiel As Integer = "123" können nicht mehr passieren.
    Hallöchen, falls du nicht so sehr an der Lernkurve interessiert bist, oder auch aus Quellcodes schlau wirst könntest du folgendes ansehen.
    Wenn du lieber selbst forschen willst, oder jemand anderes dir einen "Anstoß" geben kann, dann schau es dir vielleicht eher nicht an.
    Spoiler anzeigen

    Ist in C# und relativ kurz:
    dotnet-snippets.de/snippet/gro…amen-teiler-berechnen/192
    (Natürlich sollte man selbst programmieren, aber einen allgemeinen Algorithmus muss man nicht jedes mal neu erfinden)
    Du kannst ihn mit einem Converter in VB.Net übersetzen oder versuchen selbst umzuschreiben, das geht!

    C#-Quellcode

    1. /// <summary>
    2. /// GGT der Zahlen A und B bestimmen.
    3. /// </summary>
    4. /// <returns></returns>
    5. public static int ggT(int a, int b)
    6. {
    7. int functionReturnValue = 0;
    8. if (a < 0)
    9. {
    10. a = a * (-1);
    11. }
    12. while (b > 0)
    13. {
    14. functionReturnValue = a % b;
    15. a = b;
    16. b = functionReturnValue;
    17. }
    18. return a;
    19. }


    Um das Verhältnis aus dem ggT zu bestimmen kannst du hier ebenfalls x = a/ggt; y= b/ggt machen.

    こんにちわ
    Achte beim stellen von Fragen auf eine genaue Fragestellung, mir passiert das selbst häufig, andere können dir dann nicht so gut helfen.

    LuaX schrieb:

    C#-Quellcode

    1. a = a * (-1);
    machst Du

    C#-Quellcode

    1. a = -a;
    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!
    @LuaX Vielen Dank. Geht ja doch sehr kurz. Ich hätte gleich googlen sollen, statt es selbst zu machen. Wobei man ja auch immer selbst etwas entwickeln will. Aber du hast Recht, ein GGT-Algo ist bereits allgemein und man muss ihn nicht neu erfinden.

    Am Ende habe ich noch Return (VerhaeltnisTeil1 / a).ToString & ":" & (VerhaeltnisTeil2 / a).ToString geschrieben, damit ein String zurückgegeben wird.

    VB.NET-Quellcode

    1. Public Function ggT(ByVal a As Integer, ByVal b As Integer) As String
    2. Dim VerhaeltnisTeil1 As Integer = a
    3. Dim VerhaeltnisTeil2 As Integer = b
    4. Dim functionReturnValue As Integer
    5. If a < 0 Then
    6. a = -a
    7. End If
    8. While b > 0
    9. functionReturnValue = a Mod b
    10. a = b
    11. b = functionReturnValue
    12. End While
    13. Return (VerhaeltnisTeil1 / a).ToString & ":" & (VerhaeltnisTeil2 / a).ToString
    14. End Function

    An die Neulinge: Nutzt Option Strict On und Option Infer Off. Dadurch kommt ihr mit Datentypumwandlungen nicht durcheinander und der Code verbessert sich um Einiges! Solche Fehler à la Dim Beispiel As Integer = "123" können nicht mehr passieren.
    @Bartosz

    Die interative Variante bzw. die im Link von @LuaX verwendete Methode ist genau der Euklidische Algorithmus. Siehe Wikipedia.
    de.wikipedia.org/wiki/Euklidischer_Algorithmus


    Für kleinere Zahlen verwende ich gern die rekursive Methode. Für sehr grosse Zahlen ist es jedoch sicherer über die iterative Variante zu gehen.

    VB.NET-Quellcode

    1. ​Private Function ToGCD(ByVal i1 As Int32, ByVal i2 As Int32) As Int32
    2. Return If(i2 = 0, i1, ToGCD(i2, i1 Mod i2))
    3. End Function


    Freundliche Grüsse

    exc-jdbi