Präkrement Denkfehler

M

Mart

Gast
Java:
    void insertionSort(int []arr) {
        int element, j;
        for (int i = 1; (j = i) < arr.length; i++) {
            element = arr[i];
            while ( j > 0 && arr[j-1] < element) arr[j] = arr[--j];
            arr[j] = element;
        }
    }
hier versteh ich diese Zeile nicht : arr[j] = arr[--j]
hier ist zb j = 10
dh auf der Rechten seite wird j sofort um 1 niedriger dh j=9 wenn dann der wert bestimmt wurde auf der Rechten seite wird es in der linken seite eingefügt an der stelle j=9 dh es würde mit sich selber tauschen ... nur es tverschiebt den wert richtig aber ich weis nicht warum es funtkioniert... gefühlt stell ich mich an wie der erste mensch
 

LimDul

Top Contributor
Java:
    void insertionSort(int []arr) {
        int element, j;
        for (int i = 1; (j = i) < arr.length; i++) {
            element = arr[i];
            while ( j > 0 && arr[j-1] < element) arr[j] = arr[--j];
            arr[j] = element;
        }
    }
hier versteh ich diese Zeile nicht : arr[j] = arr[--j]
hier ist zb j = 10
dh auf der Rechten seite wird j sofort um 1 niedriger dh j=9 wenn dann der wert bestimmt wurde auf der Rechten seite wird es in der linken seite eingefügt an der stelle j=9 dh es würde mit sich selber tauschen ... nur es tverschiebt den wert richtig aber ich weis nicht warum es funtkioniert... gefühlt stell ich mich an wie der erste mensch
Es wird von links nach rechts ausgewertet.

Das heißt, zuerst wird
Code:
arr[j]
ausgewertet - da ist j noch 10.
Nun wird
Code:
arr[--j]
ausgewertet. Da es sich hier um einen Pre-Operator handelt, wird zuerst der Wert gesenkt, bevor er ausgewertet wird. Ergo wird aus 10 der Wert in j und wird er verwendet. Damit ergibt sich folgendes nach der Auswertung
Java:
// Hier ist j noch 10
arr[10] = arr[9];
// Hier ist j dann dann 9

Anders wäre es übrigens, wenn da stehen würde
Java:
arr[--j] = arr[j]
das wäre eine Zuweisung an sich selber :)
 
Zuletzt bearbeitet:
K

kneitzel

Gast
Ich finde die JLS gut. Die ist sehr klar und deutlich geschrieben und gibt eine super Grundlage für jede Java bezogene Kommunikation, da Begriffe recht deutlich verwendet / definiert werden.
 

mihe7

Top Contributor
Manche Dinge (wenn ich es richtig im Kopf habe, z. B. die Operatorenreihenfolge) sind aber auch reichlich kompliziert und schlecht nachvollziehbar in der JLS.
 

Barista

Top Contributor
Ihr habt recht, hätte ich bei einer Zuweisung (Assignment) nicht gedacht:
[CODE lang="java" title="InsertionSortWithPreDekrement"]import java.util.Arrays;

public class InsertionSortWithPreDekrement {

public static void main(String[] args) {

final int[] arr = new int[] { 0 , 1 , 2 , 3 };

System.out.println( Arrays.toString( arr ) );

insertionSort( arr );

System.out.println( Arrays.toString( arr ) );
}

static void insertionSort(int []arr) {
int element, j;
for (int i = 1; (j = i) < arr.length; i++) {
element = arr;
while ( j > 0 && arr[j-1] < element)
{
arr[j] =
arr[--j];
}

arr[j] = element;
}
}
}
[/CODE]

[CODE lang="java" title="InsertionSortWithPreDekrementWithMyArr"]import java.util.Arrays;

public class InsertionSortWithPreDekrementWithMyArr {

private static class MyArr {
private final int[] innerArr;

/**
* Constructor.
*
* @param innerArr
*/
public MyArr(final int size) {
this.innerArr = new int[size];
}

int length() {
return this.innerArr.length;
}

void set(int index, int value) {
System.out.println( "set[" + index + "]=" + value);
innerArr[index] = value;
}

int get(int index) {
final int value = innerArr[index];
System.out.println( "get " + value + "[" + index + "]");
return value;
}

@Override
public String toString() {
return Arrays.toString(innerArr);
}

}

public static void main(String[] args) {

final MyArr arr = new MyArr( 4 );
arr.set( 0 , 0 );
arr.set( 1 , 1 );
arr.set( 2 , 2 );
arr.set( 3 , 3 );

System.out.println( arr );

insertionSort( arr );

System.out.println( arr );
}

static void insertionSort(MyArr arr) {
int element, j;
for (int i = 1; (j = i) < arr.length(); i++) {
element = arr.get(i);
while ( j > 0 && arr.get(j-1) < element)
{
arr.set(j ,
arr.get(--j) );
}

arr.set(j , element );
}
}
}
[/CODE]

[CODE lang="java" title="InsertionSortWithoutPreDekrement"]import java.util.Arrays;

public class InsertionSortWithoutPreDekrement {

public static void main(String[] args) {

final int[] arr = new int[] { 0 , 1 , 2 , 3 };

System.out.println( Arrays.toString( arr ) );

insertionSort( arr );

System.out.println( Arrays.toString( arr ) );
}

static void insertionSort(int []arr) {
int element, j;
for (int i = 1; (j = i) < arr.length; i++) {
element = arr;
while ( j > 0 && arr[j-1] < element)
{
int tmp = arr[j - 1];
arr[j] = tmp;
j--;
}

arr[j] = element;
}
}
}
[/CODE]

Jedesmal auf der Konsole:

Code:
[0, 1, 2, 3]
[3, 2, 1, 0]
 
K

kneitzel

Gast
Manche Dinge (wenn ich es richtig im Kopf habe, z. B. die Operatorenreihenfolge) sind aber auch reichlich kompliziert und schlecht nachvollziehbar in der JLS.
Das Problem ist nun einmal, dass die JLS versucht, hoch exakt zu sein, damit keinerlei Missverständnisse auftreten. Dazu wird dann mit sehr vielen Fachbegriffen um sich geworfen, die man kennen muss.

Man muss sich nur einmal den Abschnitt des Prefix Decrement Operator -- ansehen:

15.15.2. Prefix Decrement Operator --​

A unary expression preceded by a -- operator is a prefix decrement expression.

The result of the unary expression must be a variable of a type that is convertible (§5.1.8) to a numeric type, or a compile-time error occurs.

The type of the prefix decrement expression is the type of the variable. The result of the prefix decrement expression is not a variable, but a value.

At run time, if evaluation of the operand expression completes abruptly, then the prefix decrement expression completes abruptly for the same reason and no decrementation occurs. Otherwise, the value 1 is subtracted from the value of the variable and the difference is stored back into the variable. Before the subtraction, binary numeric promotion (§5.6) is performed on the value 1 and the value of the variable. If necessary, the difference is narrowed by a narrowing primitive conversion (§5.1.3) and/or subjected to boxing conversion (§5.1.7) to the type of the variable before it is stored. The value of the prefix decrement expression is the value of the variable after the new value is stored.

Note that the binary numeric promotion mentioned above may include unboxing conversion (§5.1.8) and value set conversion (§5.1.13). If necessary, format conversion is applied to the difference prior to its being stored in the variable.

A variable that is declared final cannot be decremented because when an access of such a final variable is used as an expression, the result is a value, not a variable. Thus, it cannot be used as the operand of a prefix decrement operator.
Der erste Satz ist noch eine klare Definition aber alles, was danach kommt, ist garantiert nicht einfach. Viele Begriffe muss man kennen. 6 Referenzen auf Kapitel 5 ... Das Kapitel 5 sollte man also auch kennen ... (Da wird man natürlich auch extrem viel an Verweisen finden).

Damit ist klar: Das ist nichts für einen Anfänger. Auch in der Praxis will man in der Regel schnell irgend eine Anwendung haben - da ist die exakte Definition unwichtig. Da ast z.B. Operator Precedence als Beispiel gebracht - und da ist dann eine Tabelle wie man sie von vielen Seiten kennt, übersichtlicher. Aber wenn man das dann vergleicht, dann merkt man, dass da einiges weggelassen wurde (Das i.d.R. auch niemanden interessieren mag, der zu der Seite kommt).

Daher bin ich da voll und ganz bei Dir.

Nur wieso ist die JLS dann wichtig? Auch hier für das Forum?

Ich bin der Meinung, dass man klare Definitionen von Begriffen braucht. Dinge müssen sauber bezeichnet werden. Das ist die Grundlage für jede Kommunikation und das ist nun einmal genau das, was wir hier im Forum betreiben.

Da mag manch Einer sagen: Das ist doch alles egal.
- Der Reminder Operator ist Modulo!
- Der Konstruktor ist eine Methode! (Daher müssen Methoden auch keinen Return Type oder das void haben!)
- Generell kann man hier ja beliebige Namen nutzen (Funktionen, Prozeduren, ....)
...

Wir würden es im Forum recht schwer haben mit unserer Kommunikation, weil unklar ist, was mit Begriffen gemeint ist. Und es würde dann auch schlicht etwas falsches im Forum stehen.

Daher ist es hier wie in der Philosophie mit Kant:
Man kann für oder gegen ihn argumentieren - aber nie ohne ihn. (Er hat halt sehr gute Arbeit geleistet bei der Definition von Begriffen.)

Was ist denn dann die Erwartungshaltung, wenn ich z.B. die JLS zitiere?

Ich zitiere ja in der Regel nicht einfach die JLS. Ich bringe eine Anmerkung und verweise dann lediglich auf die JLS, da dort eben die Definition zu finden ist. Da muss niemand die JLS lesen. Von einem Anfänger erwarte ich das auch nicht. Aber das ist ja, wie Sprache gelernt wird: Es wird verwendet und wenn der Begriff falsch verwendet wird, dann wird man verbessert. ("Nein, das ist keine Biene, das ist eine Wespe. Eine Biene ist dicker und ....") Und dann wird man das (hoffentlich) annehmen.
Nur ich bin nicht in einer Rolle, die mir diese Verbesserung gestattet (Elternteil eines Kindes z.B.), daher kann ich mich nur auf andere Quellen beziehen. Und da kommt dann die Frage auf, was denn brauchbare Quellen sind. Was für Anforderungen müssen erfüllt sein?
- Korrektheit - ich denke, das ist klar. (Und ein riesen Problem bei den "dahergelaufenen" Blogs und YT Videos. Reminder als Modulo zu bezeichnen ist da ja fast üblich!)
- Vollständigkeit - wenn die Hälfte fehlt, ist es zumindest problematisch
- Anerkannt - Es muss natürlich anerkannt sein. Ich kann ja meine eigene Java Language Specification schreiben mit neuen Begriffen...

Ein einfach zu lesen ist da eben explizit nicht die Anforderung. (Und auch in der Philosophie hat niemand behauptet, dass Kant einfach zu lesen ist. Und manch ein Student hat da dann auch lieber zu einem "Kant Lexikon" gegriffen ... Das sehe ich hier nicht anders.

Und da habe ich bisher nichts besseres gefunden als die JLS.

Das einfach einmal als keine Sichtweise von mir zu dieser Thematik. Man merkt halt vielleicht, dass da doch etwas mehr Gedanken dahinter stecken.

Und wer ist Schuld?
Natürlich muss man hier in Deutschland die Schuldfrage behandeln? Wer ist denn nun schuld? Und natürlich kann ich die Schuld ganz klar zuweisen. Ich bin nicht verantwortlich, auch wenn @temi das mehr als deutlich sagen wollte! Schuld ist natürlich ganz allein @mrBrown! Hätte er mich hier im Forum nicht bezüglich Begriffen zurecht gewiesen (Was kann ich dafür, dass er die .Net / C# Begriffe nicht gut kennt?), dann wäre das alles nie passiert und ich hätte nie die JLS in irgend einer Weise angerührt!

Edit:
Auch noch ganz interessant ist natürlich die Herangehensweise:
Das hat man u.A. im Studium gemerkt: Die Leute waren gewohnt, dass alles von klein auf aufgebaut wird. Wir haben dieses und dann kommt ein kleines Steinchen oben drauf ... und dann noch ein Teil ... und noch ein Teil ... UPS - da haben wir ja jetzt plötzlich was Neues ...
Das Vorgehen im Studium war dann plötzlich anders herum:
Es gibt ein paar Definitionen. Und dann folgert man etwas daraus. Da war Informatik dann nicht mehr ein "Wir lassen mal ein Robot wandern und Steine aufheben" sondern es ging um Syntax, Semantik, .... Klare Definitionen, Klare Folgerungen ... Da wurde am Ende bewiesen, dass ein Code das macht, was er machen sollte. (Um ein Thema heraus zu greifen)
Das ist hier aus meiner Sicht durchaus ähnlich.
 
Zuletzt bearbeitet von einem Moderator:
K

kneitzel

Gast
Eines verstecke ich nicht wo in diesen Thread ist hier mrBrown?
Als ob @mrBrown irgendwo beteiligt sein müsste, um schuld zu sein.

@mrBrown weist nun einmal regelmäßig auch auf gewisse Dinge hin. Das mag Dir so noch nicht aufgefallen sein, aber das ist so.
Am "Modulo" Thread warst Du doch auch beteiligt, oder nicht? Da war der erste Hinweis, dass es bei Java um Remainder geht und nicht um Modulo z.B. von ihm. Oder habe ich das falsch in Erinnerung?
 

Jw456

Top Contributor
Als ob @mrBrown irgendwo beteiligt sein müsste, um schuld zu sein.

@mrBrown weist nun einmal regelmäßig auch auf gewisse Dinge hin. Das mag Dir so noch nicht aufgefallen sein, aber das ist so.
Am "Modulo" Thread warst Du doch auch beteiligt, oder nicht? Da war der erste Hinweis, dass es bei Java um Remainder geht und nicht um Modulo z.B. von ihm. Oder habe ich das falsch in Erinnerung?
Stimmt, finde es doch etwas merkwürdig jemanden zu benutzen der am geschehen nicht beteiligt ist war.
 
K

kneitzel

Gast
Stimmt, finde es doch etwas merkwürdig jemanden zu benutzen der am geschehen nicht beteiligt ist war.
Ich finde es merkwürdig, wenn Leute einfache Texte nicht verstehen und dann Passagen aus dem Kontext ziehen. Besonders irritierend, wenn offensichtliche Späße nicht erkannt werden.

Ansonsten: Ich versuche Trolle weniger zu füttern, daher bitte ich um Verständnis, wenn ich Dir nicht ausführlicher antworte.
 

Jw456

Top Contributor
Ich finde es merkwürdig, wenn Leute einfache Texte nicht verstehen und dann Passagen aus dem Kontext ziehen. Besonders irritierend, wenn offensichtliche Späße nicht erkannt werden.

Ansonsten: Ich versuche Trolle weniger zu füttern, daher bitte ich um Verständnis, wenn ich Dir nicht ausführlicher antworte.
Ich hoffe das Du keine Doktorarbeit darüber machst.

Meine Frage wurde schon beantwortet wenn du da noch einen drauf geben musst deine Sache.
 

Ähnliche Java Themen

Neue Themen


Oben