PHP-Programm optimieren

Redbull

Abenteurer
Hey Leute,
Ich hab mal ne kleine Frage zu folgendem PHP-Programm:

PHP:
<?
if($a<b)
{$c=$a;
{$a=$b; 
{$b=$c;}
do
{  $a=$a-$b;
if($a<$b)
{$c=$a;
{$a=$b; 
{$b=$c;};
}while ($a!=$b);
echo"<br>xxx: ",$b;
?>


Die Frage von meinem Lehrer lautet, ich zitiere:"Optimieren Sie das Programm in Länge, Funktionalität und Ausgabe."

Ich bin bisher soweit, dass
PHP:
if($a<$b)
{$c=$a;
{$a=$b; 
{$b=$c;}

zweimal enthalten ist und man dies sicher kürzen könnte. Aber jegliche Versuche scheiterten.

Könntet ihr mir da helfen?
 
Deine Schachtelung mittels geschweifter Klammern haut hinten und vorn nicht hin. Kontrollier das noch mal.

Der von dir ausgesuchte Schnippsel ist schon mal ein guter Ansatzpunkt. Man kann ihn durch geschicktes Umstellen der Schleife einmal entfernen. Der implementierte Algorithmus wird oft anders implementiert, ohne dieses Stück Code. Wenn du herausfindest, was das Stück Code tut kommst du vielleicht darauf, wie du ihn komplett weglassen kannst.

Der Algorithmus ist übrigens sehr bekannt, auch wenn ich dir den Namen nicht verraten werde, du sollst schließlich was lernen und nicht bei Wikipedia abschreiben.
 
Hey, danke für die Antwort.

PHP:
<?
if($a<b)
{$c=$a;
$a=$b; 
$b=$c;}
do
{  $a=$a-$b;
if($a<$b)
{$c=$a;
$a=$b; 
$b=$c;};
}while ($a!=$b);
echo"<br>xxx: ",$b;
?>

Oh, da war ein kleiner Flüchtigkeitsfehler. Denke jetzt ist es richtig.



Das Stück Code prüft erst ob a kleiner als b ist. Falls ja, tauscht es die Werte a und b in dem es den Wert nach c auslagert. Aber ich weiß wirklich nicht, was man in der Schleife umstellen muss.

Aber etwas abgeändert werden muss ja auf jeden Fall.
Weil ja sowohl vor als auch nach dem
PHP:
{  $a=$a-$b;
der Code ausgeführt werden muss.
 
Zuletzt bearbeitet:
Hast du den Code mal wenigstens getestet?
Denn dann wüsstest du vielleicht was er macht. Naja ich kenn den Algorithmus hauptsächlich mit Modulo.

also:
1.
PHP:
if($a<b)
sollte so aussehen:
PHP:
if($a<$b)
2.
PHP:
do
{  $a=$a-$b;
if($a<$b)
{$c=$a;
$a=$b; 
$b=$c;};
}while ($a!=$b);
ist fehlerhaft, da sich wenn $a = $b das ganze aufhängt! Hier sollte man eine kopfgesteuerte und keine fußgesteuerte Schleife nehmen.

3. Muss das mit $a < $b nur vor der Subtraktion ausgeführt werden nicht aber danach, heißt einfach in der Schleife beides verdrehen.

4. Hättest du dann zweimal das mit $a < $b nacheinander stehen was aber entweder nur keinmal oder einmal ausgefürt, da wenn getauscht wird das zweite mal immer $a >= $b gilt, so dass dann eines von beiden weg kann und zwar das vor der Schleife.

5. Wenn $a oder $b < 1 sind dann hast du ein Problem!

6. Hast du auch ein Problem falls $a oder $b keine ganzen Zahlen sind!

7. Ist der Stil des Codes grässlich da er wahrscheinlich nicht einmal welchen hat.

8. Ginge das ganze wie Jubidu sagt auch anders aber nun gut ich glaub das war nicht Ziel der Aufgabe.

Hier mal eine Lösung von mir:
PHP:
<?php
    if( isset($_GET['a']) )
        $a = (int) $_GET['a'];
    else
        $a = 0;

    if( isset($_GET['b']) )
        $b = (int) $_GET['b'];
    else
        $b = 0;



    echo 'Zahl 1 = '.$a."<br />\n";
    echo 'Zahl 2 = '.$b."<br />\n";
    echo 'Größter gemeinsamer Teiler: ';

    if($a > 0 && $b > 0) {
        while($a != $b) {
            if($a < $b) {
                $c = $a;
                $a = $b; 
                $b = $c;
            }

            $a = $a - $b;
        }

        echo $b."<br />\n";
    }
    else
        echo "Nicht definiert!<br />\n";
?>
 
Zuletzt bearbeitet von einem Moderator:
Ok, danke auch dir.

Allerding verstehe ich dein Programm nicht. Ich bin einfach nicht so weit.
Hatte jetzt 2 Stunden. Erste Stunde war HTML-Crashkurs, zweite PHP-Anfang.
Ich versuch daraus jetzt mal ein optimiertes Programm zu schreiben.

Danke euch!
 
Hast du den Code mal wenigstens getestet?
Denn dann wüsstest du vielleicht was er macht. Naja ich kenn den Algorithmus hauptsächlich mit Modulo.

Ich auch, aber das ist hier nicht gefragt.

2.
PHP:
do
{  $a=$a-$b;
if($a<$b)
{$c=$a;
$a=$b; 
$b=$c;};
}while ($a!=$b);
ist fehlerhaft, da sich wenn $a = $b das ganze aufhängt! Hier sollte man eine kopfgesteuerte und keine fußgesteuerte Schleife nehmen.

Nö. Das passt semantisch. Es ist kein schöner Stil, aber darum geht es ja wohl bei der Aufgabe, den gräßlichen Code in schönen Code umzubauen.

3. Muss das mit $a < $b nur vor der Subtraktion ausgeführt werden nicht aber danach

Wird es doch. $a und $b werden sortiert, bevor die nächste Subtraktion vorgenommen wird. Optimal ist es so nicht, aber korrekt schon.

5. Wenn $a oder $b < 1 sind dann hast du ein Problem!

6. Hast du auch ein Problem falls $a oder $b keine ganzen Zahlen sind!

7. Ist der Stil des Codes grässlich da er wahrscheinlich nicht einmal welchen hat.

Nachdem der Code wohl vom Lehrer vorgegeben war wohl kaum sein Problem. Aber grundsätzlich hast du natürlich recht.


Eine Optimierung wurde dir schon genannt, die Verwendung einer while()-Schleife statt einer do ... until()-Schleife und dann die erste Sortierung von $a und $b ($a soll ja immer größer als $b sein) wegzulassen.

Man könnte die Vertauschung von $a und $b auch ganz weglassen. Wie?

P.S.: Was berechnet der Algorithmus?

P.P.S.: Die Fragen sind an den Threadersteller gerichtet!
 
Was genau verstehst du da nicht?

Ich versuchs mal etwas zu erklären:
if( isset($_GET['a']) )
$a = (int) $_GET['a'];
else
$a = 0;
Ich hole die Parameter welche über Get übergeben wurden. Es gibt zwar mehrere Wege das ist aber mitunter die einfachste. Das funktioniert so:
Du gibst in der URL das hier ein: http://blabla.bla/script.php?a=1&b=2&c=3
Dabei bedeutet das ? dass hinter dem Skript Variablen per Get Methode übermittelt werden und zwar nach dem Schema Variablenname = Variableninhalt. Die Variablen werden mit & voneinander getrennt. Man kann auch Text und ähnliches so übergeben aber Achtung, Sonderzeichen sind nicht erlaubt (dazu zählen auch Leerzeichen, &, Umlaute, usw.), dafür muss man das ganze escapen aber das ist gerade egal.

Die Variablen stehen dann im Skript selbst in dem Array $_GET['Variablenname'] zur verfügung. Mit isset prüfe ich ob diese existiert denn ich kann ja schlecht was nutzen was es gar nicht gibt. Und falls es diese Variable gibt dann weise ich den Inhalt der über URL kommt meiner Variablen $a zu, das (int) ist dabei ein Typecast und erzwingt sozusagen eine Umwandlung in eine Ganzzahl, so dass Kommazahlen Text und sonstiges so fern möglich in eine Ganze Zahl umgewandelt werden.

echo 'Zahl 1 = '.$a."<br />\n";
echo 'Zahl 2 = '.$b."<br />\n";
echo 'Größter gemeinsamer Teiler: ';
Das hier ist lediglich die Ausgabe. Hoffe du verstehst das alles. Kleine Info normale ' stehen für normalen Text es werden keine Ersetzungen durchgeführt ist auch die schnellste Art der Ausgabe (abgesehen von direktem HTML), auch wenn die Unterschiede nur messbar gering sind. Text in " wird jedoch ersetzt, so dass wenn man $X schreibt da der Inhalt der Variablen mit dem Namen X reinkopiert wird wohingegen bei ' direkt der Text $Variable und nicht der Inhalt der Variablen X ausgeben wird. Hinzu kommt dass man unter " escapesequenzen wie \n (Neue Zeile), \t (Tab) und ähnliches nutzen kann. Der Punkt dient zum verbinden von Zeichenketten, Zahlen werden da automatisch in Zeichenkettenumgewandelt, verbunden und dann ausgegeben.

if($a > 0 && $b > 0) {
while($a != $b) {
if($a < $b) {
$c = $a;
$a = $b;
$b = $c;
}

$a = $a - $b;
}

echo $b."<br />\n";
}
else
echo "Nicht definiert!<br />\n";
Das if($a > 0 && $b > 0) prüft ob beide Zahlen größer sind als 0 denn wenn sie es nicht sind haut die ganze Sache nicht hin und es wird Nicht definiert ausgeben! Wenn sie aber größer sind wird die Berechnung von deinem Programm durchgeführt.

ich nutze while (Bedingung) { ... } was eine Kopfgesteuerte Schleife ist du nutzt do { ... } while (Bedingung) was eine Fußgesteuerte Schleife ist, der Unterschied ist der dass bei einer Kopfgesteuerten Schleife erst geprüft wird und dann die Anweisungen ausgeführt werden, so dass wenn die Bedingung am Anfang nicht stimmt diese niemals ausgeführt wird, wohingegen bei der Fußgesteuerten Schleife erst die Anweisungen ausgeführt werden und erst dann geprüft wird, so dass bei der Fußgesteuerten Schleife die Anweisungen immer mindestens einmal ausgeführt werden auch wenn die Bedingung falsch ist. Ich nutze die Kopfgesteuerte da wenn $a = $b bei mir der Code nicht ausgeführt wird da ja schon das Ergebnis da ist, würde der Code ausgefürht werden, würde er Mist bauen und sich aufhängen weil dann diese Bedingung nachher nicht mehr zutreffen wird (Endlosschleife).

Und ansonsten habe ich die Umstellungen vorgenommen wie ich vorher erwähnt hatte das Tauschen vor die Subtraktion und das Tauschen außerhalb der Schleife entfernt.

Ach und noch was {} sind bei if, while und sonstigen Dingen nicht immer nötig!
das hier ist zum Beispiel das gleiche:
PHP:
if (...) {
$a = 1;
}
else {
$a = 0;
}
wie das hier:
PHP:
if (...)
$a = 1;
else
$b = 1;
Jedoch sind die hier nicht gleich:
PHP:
if (...) {
$a = 1;
$b = 2;
}
else {
$a = 0;
$b = 3
}
PHP:
if (...)
$a = 1;
$b = 2;
else
$b = 1;
$b = 3;
Denn ein if oder ein while zum Beispiel führt immer nur die nächste Anweisung durch niemals 2 oder 3. Will man jedoch mehrere Anweisungen zu einem if packen muss man das ganze mit {} gruppieren wodurch dann x-beliebige Anweisungen zu einer einzigen Anweisung werden (aus Sicht der Syntax). Diese Gruppierungen kann man sogar beliebig im Code durchführen (auch ohne if, while oder sonstigem) zum Beispiel so:
$a = 1;
{
$b = 2;
$c = 3;
}
$d = 4;
Hinzu kommt noch dass ein einzelnes ; an sich das Ende einer Anweisung bedeutet steht nix davor ist es die leere Anweisung.
So dass dann folgendes nicht identisch ist:
PHP:
if (...);
$a = 1;
PHP:
if (...)
$a = 1;
Wie gesagt führt ein if immer nur die nächste Anweisung durch, im oberen Fall ist es die leere Anweisung so dass das $a immer ausgeführt wird egal ob die Bedingung im if nun True oder False liefer. Im zweiten Fall ist die nächste Anweisung aber $a = 1; so dass es nur bei True in der Bedingung ausgeführt wird aber nicht bei False. Selbes gilt natürlich für Schleifen wie while.

Ach außerdem solltest du dir Gedanken um die Gestaltung deines Codes machen denn so wie dein Code bisher aussah wirst du sehr flott Probleme bekommen. Aber es gibt auch relativ viele Unterschiedliche Stile ich bevorzuge meinen. Was du aber aufjedenfall machen solltest ist Einrücken! Und ggf. leere Zeilen wenn was neues kommt, das ist einfach Pflicht!

Hier mal ein paar Stile: http://de.wikipedia.org/wiki/Einr%C3%BCckungsstil
ist fehlerhaft, da sich wenn $a = $b das ganze aufhängt! Hier sollte man eine kopfgesteuerte und keine fußgesteuerte Schleife nehmen.
Nö. Das passt semantisch. Es ist kein schöner Stil, aber darum geht es ja wohl bei der Aufgabe, den gräßlichen Code in schönen Code umzubauen.
Es geht mir hier nicht um Schönheit sondern dass bei gewissen Konstellationen sich das Skript in einer Endlosschleife aufhängt! Teste es.
3. Muss das mit $a < $b nur vor der Subtraktion ausgeführt werden nicht aber danach
Wird es doch. $a und $b werden sortiert, bevor die nächste Subtraktion vorgenommen wird. Optimal ist es so nicht, aber korrekt schon.
Lies mal genau, ich sagte nicht dass es das nicht wird sondern dass es nur also einmal ausgeführt werden muss. Hier ging es um eine Optimierung die eben von der Aufgabe verlangt ist!

Ach falls du die ganzen Skripte auch mal testen willst setz dir nen PHP Server auf, zum Beispiel den hier: http://www.apachefriends.org/de/xampp.html Aber Achtung er ist nicht auf Sicherheit getrimmt am Besten versteckst du ihn hinter einer Firewall.
 
Zuletzt bearbeitet von einem Moderator:
Danke für euer Engagement und die Antworten.

Aber eigentlich wollte ich erstmal bei den Sachen bleiben die wir im Unterricht schon haben. Und das sind momentan nur Do-While-Schleifen, While-Schleifen und normale Anweisungen. Ich hab momentan auch nicht die Zeit, mich privat damit ausführlich auseinander zusetzen.

Dass das Programm bei einigen Werten nicht funktioniert ist mir durchaus bewusst. Die Frage nach eben diesen Werten hat uns unser Lehrer auch gestellt.

Ich werd morgen mal meine optimierte Version posten. Jetzt hab ich da gerade keinen Nerv zu. :-D