Verstehe folgenden Code nicht

TechSenpai

Cadet 3rd Year
Registriert
Sep. 2018
Beiträge
58
Hey
Ich lerne gerade Java mittels eines Buches und als kleineres Beispiel wurde folgender Code verwendet:

void kuerzen(){
int m, n, r;
m = Math.abs(zaehler);
n = Math.abs(nenner);
r = m % n;
while (r > 0) {
m = n;
n = r;
r = m % n;
}
zaehler /= n;
nenner /= n;

Ich verstehe gar nichts ab m = n; hier wird mir nämlich nicht deutlich weshalb m plötlich = n sein sollte??
Könnte mir das bitte jemand noch mal erklären
Edit: Wäre eventuell sinnvoll zu wissen wofür der Code ist: Der Code sollte einen Bruch kürzen!
LG
SC
 
Zuletzt bearbeitet:
Nimm den Bruch 25/35 und geh den Code durch. Welchen Wert hat m? Welchen Wert hat n? Welchen Wert hat r? Ist die Bedingung für die while-Schleife erfüllt? Falls ja, Was passiert dann dort?
 
  • Gefällt mir
Reaktionen: BeBur
Das Problem ist also nicht Java, sondern Mathematik. Google mal nach Euklidischem Algorithmus. Deine Variante macht sich zusätzlich den in Java vorhandenen Modulo-Operator zunutze.
 
  • Gefällt mir
Reaktionen: rg88 und bart0rn
Ist das eigentlich normal in solchen Büchern mit Buchstaben um sich zu werfen? Gibt es irgendeinen Grund auf sprechende Variablennamen zu verzichten? Just wondering, glaube bei mir war es auch damals so. Das ist ja grausam.
 
  • Gefällt mir
Reaktionen: BAGZZlash und Nilson
Das in der Algebra absolut üblich mit Buchstaben für unbekannte Größen zu rechnen. Womit auch sonst?
Kann man die im Quelltext anders benennen: Ja.
Wird dadurch die Übersicht gesteigert: Nicht unbedingt. Vor allem, wenn man Clean Code Paradigmen umsetzt ist es so möglich mathematische Algorithmen von der restlichen Modullogik zu unterscheiden. In der Regel verwendet man für seine Symbole ja eine camelCase oder snake_case Schreibweise.
So kann man dann Mathematische Größen im Quelltext von restlichen Symbolen / Variablen, mit denen nicht gerechnet wird, unterscheiden.
 
Clean Code Paradigma beinhaltet ausdrucksstarke Variablennamen. Der Algorithmus ist auch sowieso getrennt von der restlichen Logik, weil du sonst verschiedene Ebenen miteinander vermischen würdest (auch Clean Code Paradigma).
In der Mathematik verwendet man einzelne Buchstaben weil es so übersichtlicher ist, in Code ist es hingegen genau umgekehrt.
 
  • Gefällt mir
Reaktionen: BAGZZlash, Burfi und pvcf
BeBur schrieb:
Ist das eigentlich normal in solchen Büchern mit Buchstaben um sich zu werfen? Gibt es irgendeinen Grund auf sprechende Variablennamen zu verzichten? Just wondering, glaube bei mir war es auch damals so. Das ist ja grausam.

Schrecklich, so einen bescheidenen Code in ein Anfängerbuch zu bringen.

ayngush schrieb:
Das in der Algebra absolut üblich mit Buchstaben für unbekannte Größen zu rechnen. Womit auch sonst?
Kann man die im Quelltext anders benennen: Ja.
Wird dadurch die Übersicht gesteigert: Nicht unbedingt. Vor allem, wenn man Clean Code Paradigmen umsetzt ist es so möglich mathematische Algorithmen von der restlichen Modullogik zu unterscheiden.

Robert Martin würde dir aufs Hausdach steigen, wenn du Variablen n, m und r nennen würdest.
"r" kann ich halbwegs nachvollziehen durch "rest", aber selbst das ist Raten und nicht Wissen.
Durch das Einhalten von Abstraktionsleveln sollten (mathematische) Algorithmen eh nie in die Quere kommen.
 
  • Gefällt mir
Reaktionen: BAGZZlash, Burfi, pvcf und eine weitere Person
Ja, keine Ahnung. Niemand würde KathetenquadratEins² + KathetenquadratZwei² = Hypotenusenquadrat² schreiben und wenn doch: Was war mit euch los, als Algebra lief?
mastaqz schrieb:
aber selbst das ist Raten und nicht Wissen.
m = Math.abs(zaehler);
n = Math.abs(nenner);

Noch sauberer kann man das im Quelltext nicht mehr darstellen.
Die Variablen haben klingende Namen. Die in der Formel verwendeten Symbole logisch absolut korrekte Buchstabenzuordnungen (m, n und r).

Ich weiß absolut nicht, was daran verkehrt sein soll?!
 
  • Gefällt mir
Reaktionen: RalphS
Gut, ich denke die Meinungen sind dazu ganz gut dargestellt worden. Bringt dem TE jetzt ja auch nichts, wenn wir das hier in seinem Thread breittreten.
 
  • Gefällt mir
Reaktionen: BAGZZlash
BeBur schrieb:
Ist das eigentlich normal in solchen Büchern mit Buchstaben um sich zu werfen? Gibt es irgendeinen Grund auf sprechende Variablennamen zu verzichten?

Ich glaube, dass das von den Mathematikern aus in die Informatik eingewandert ist. x, y, f, g, m, n, i usw.
Ich muss mich auch jedes mal zwingen, beim Coden gescheite Namen zu vergeben
 
ayngush schrieb:
Das in der Algebra absolut üblich mit Buchstaben für unbekannte Größen zu rechnen. Womit auch sonst?
also ich verwende auch in der Mathematik häufig mehr als ein Zeichen.
Ich kann so viel besser darüber nachdenken, was ich machen.

m = Math.abs(zaehler);
n = Math.abs(nenner);
das m finde ich hier btw. ziemlich verwirrend - wieso nicht z oder zAbs?
 
Die Frage des TE bezog sich nicht auf die Bezeichnung der Variablen, sondern auf darauf was im Code effektiv passiert und wieso.

SenseiComplex schrieb:
Ich verstehe gar nichts ab m = n; hier wird mir nämlich nicht deutlich weshalb m plötlich = n sein sollte??
Könnte mir das bitte jemand noch mal erklären
Das ist eine Form von Rekursion. Die While-Schleife wird solange fortgeführt und die Werte für m bzw. n durchgeschoben bis der berechnete Rest = 0 ist.

Beim euklidischen Algorithmus wird solange der Rest zweier Zahlen berechnet bis er 0 ist ==> der größte gemeinsame Teiler (ggT). Im ersten Schritt rechnet man mit Zähler und Nenner den Rest aus. Ist der Rest = 0, kann man direkt um den Nenner kürzen (zB 8/4 => 2/1). Bleibt ein Rest wird erneut der berechnet ob ein Rest bleibt, in diesem Falle aber der Rest vom Nenner und dem vorherigen Rest, das "Fenster" wird also einfach einen weitergeschoben. Bleibt auch hier ein Rest, steigt man wieder eine Ebene tiefer, schiebt das Fenster einen weiter und berechnet den Rest aus dem vorvorherigen und dem vorherigen Rest, usw. In dem Schritt, in dem der berechnete Rest = 0 ist, hat man den ggT gefunden.

Im folgenden Beispiel (C#, aber Java-like) ist die Rekursion in eine eigene Funktion ausgelagert und dadurch vielleicht einfacher zu verstehen. Die Funktion getGGT ruft sich dabei selbst solange auf bis Rest=0 gefunden wird.

C#:
void kuerzen(int zaehler, int nenner)
{
   int ggT = getGGT (zaehler, nenner);

   Console.WriteLine("ggT von {0} und {1} ist {2}", zaehler, nenner, ggt);
   Console.WriteLine("{0}/{1} = {2}/{3}", zaehler, nenner, zaehler / ggt, nenner / ggt);
}

int getGGT(int zaehler, int nenner)
{
   int rest = zaehler % nenner;
   if (rest == 0)
   {
      return nenner;      // hier wurde der GGT gefunden
   }
   else
   {
      return getGGT(nenner, rest);      // rekursiver Aufruf von getGGT mit geschobenen Werten
   }
}

Ablauf:

kuerzen (44, 12)
=> getGGT (44, 12) --> Rest = 8
==> getGGT (12, 8) --> Rest = 4
===> getGGT (8, 4) --> Rest = 0 --> ggt = 4
====> 44/12 gekürzt um 4 --> 11/3

Das gleiche passiert in der While-Schleife, aber statt rekursiven Aufrufen werden die Werte aktiv für den nächsten Durchlauf durchgeschoben.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: RalphS
Zurück
Oben