Prä- und Postinkrement

J

jDennis79

Gast
Hallo Forum,

da ich mich neben Java immer mal wieder ein bisschen mit C++ beschäftige (auf Grund mangelnden Durchhaltevermögens bislang aber nicht sehr erfolgreich), ist mir was aufgefallen. In C++ begegnet mir in Codebeispielen und -schnipseln wesentlich öfter der Präinkrementoperator, in Java hingegen häufiger der Postinkrement-Operator - ganz besonders in for-Schleifen.

Sind das einfach nur zufällig entstandene Konventionen, oder gibt es für beide Fälle begründete Argumente? Vielleicht sogar sprachspezifische? (Die Auswertungsreihenfolge kann's ja nicht sein, die ist schließlich bei beiden Sprachen gleich und spielt in for-Schleifen ja nichtmal eine Rolle.)
 
S

Spellsleeper

Gast
Soviel ich weiß haben der Prä- und der Postinkrement-Operator in C++ genau die gleiche Funktionsweise wie in Java.
Das kann eigentlich nur an der entwicklerspezifischen Verwendung liegen , zB. ob du eine For- Schleife mit 0 oder 1 anfängst.
 

XHelp

Top Contributor
In welchem Zusammenhang? In einer zusammengesetzten Form: dann muss man eben das nehmen, was Sinn ergibt.
Alleinstehend als Alternative zu "a=a+1":
Theoretisch ist i++ langsamer als ++i, da der ursprüngliche Wert ja noch zwischengespeichert werden muss. Aber sowohl in Java als auch in C wird eben viel wegoptimiert, so dass es heutzutage wohl eher unbedeutend ist.
 
J

jDennis79

Gast
Theoretisch ist i++ langsamer als ++i, da der ursprüngliche Wert ja noch zwischengespeichert werden muss. Aber sowohl in Java als auch in C wird eben viel wegoptimiert, so dass es heutzutage wohl eher unbedeutend ist.

Aha, es könnte also sein, dass man das in C++ noch häufiger antrifft, weil es sich in einer Zeit als Konvention herausgebildet hat, in der der Geschwindigkeitsunterschied noch häufiger relevant war? Und in Java eben nicht, weil Java viel jünger ist und solche minimalen Geschwindigkeitsunterschiede schon seltener ins Gewicht fielen?
 
B

bERt0r

Gast
Anscheinend ist es so, dass Java auf postinkrement optimiert wurde. Ich hab mir einen kleinen Test geschrieben:

Java:
import java.util.Date;

public class IncTest {
	
	public static void main(String args[])
	{
		long start=new Date().getTime();
		for (int i=0;i<Integer.MAX_VALUE;i++)
		{
			for(int j=0;j<10;j++){}
		}
		long end=new Date().getTime();
		System.out.println("i++ Zeit: "+(end-start));

		start=new Date().getTime();
		for (int i=0;i<Integer.MAX_VALUE;++i)
		{
			for(int j=0;j<10;++j){}
		}
		end=new Date().getTime();
		System.out.println("++i Zeit: "+(end-start));
		
		start=new Date().getTime();
		for (int i=0;i<Integer.MAX_VALUE;i+=1)
		{
			for(int j=0;j<10;j+=1){}
		}
		end=new Date().getTime();
		System.out.println("i+=1 Zeit: "+(end-start));
		
		start=new Date().getTime();
		for (int i=0;i<Integer.MAX_VALUE;i=i+1)
		{
			for(int j=0;j<10;j=j+1){}
		}
		end=new Date().getTime();
		System.out.println("i=i+1 Zeit: "+(end-start));
	}

}

Erster Durchlauf:

i++ Zeit: 27144
++i Zeit: 37893
i+=1 Zeit: 37894
i=i+1 Zeit: 27051

Zweiter Durchlauf:
i++ Zeit: 27097
++i Zeit: 37925
i+=1 Zeit: 38018
i=i+1 Zeit: 27067

Ob und in wie aussagekräftig mein Test ist sei dahingestellt, sieht aber so aus, dass i++ und i=i+1 am schnellsten sind. Ich schätze mal, weil es (für mich subjektiv) am einfachsten zu lesen ist, wurde Java auf diese 2 Konstrukte optimiert.
 
G

Gast2

Gast
Also sowas:
Java:
for(int j=0;j<10;j++){}
wird java mit sicherheit wegoptimieren ;)
Ändere da mal die zahl, du wirst keinen laufzeitunterschied feststellen.
 
G

Gas123456

Gast
@Bert:
Dein Test ist Unsinn und i++, ++i, sowie i += 1 sind alle exakt das selbe.
 

njans

Top Contributor
Also sowas:
Java:
for(int j=0;j<10;j++){}
wird java mit sicherheit wegoptimieren ;)
Ändere da mal die zahl, du wirst keinen laufzeitunterschied feststellen.

Doch wirst du :)
Eben getestet, so wird bei mir bei i++ aus 22k plötzlich 8k, wenn ich Schranke der Schleife auf 1 runter setze.
Ferner ist i++ und ++i nicht das Selbe, es würde zwar zum selben Ergebnis führen, aber bei i++ muss theoretisch noch was zwischengespeichert werden.

ich hab auch mal die inneren Schleifen gelöscht um mal zu gucken und da ist dann die benötigte Zeit ~1 -2 Sekunden bei allen ;)
 

XHelp

Top Contributor
i++, ++i, sowie i += 1 sind alle exakt das selbe.

Nö. Es gibt bei x86 Instruktionen INC und DEC. D.h. der Compiler muss erstmal erkennen, was mit i+=2 gemeint ist und es durch INC ersetzen.
Und
Code:
i++
und
Code:
++i
sind schon von der Definition her nicht das selbe.
Hast du irgendwelche Quellen für deine Aussage?
 
B

bERt0r

Gast
Die for schleifen sind dazu da, den effekt der verschiedenen Schreibweise exponentiell zu vergrößern, weil der Zeituntschied eben so gering ist. Die Schreibweise der i und j Schleife sind ja die gleichen. Ich habe die Schleifen reingetan, weil Unterschiede von ein paar 100 millisekunden ja zufällig durch einen anderen Prozess verursacht werden könnten, der dazwischenfunkt.
 
G

Gast2

Gast
Doch wirst du :)
Eben getestet, so wird bei mir bei i++ aus 22k plötzlich 8k, wenn ich Schranke der Schleife auf 1 runter setze.

Bei mir ergibt folgender Code:
Java:
long start = System.currentTimeMillis();
for (int i=0;i<Integer.MAX_VALUE;i++) {
    for(int j=0;j<10;j++){
    	// DO NOTHING
    }
}
long end = System.currentTimeMillis();
System.out.println("i++ Zeit: "+(end-start));
 
long start2 = System.currentTimeMillis();
for (int i=0;i<Integer.MAX_VALUE;i++) {
    for(int j=0;j<10000000;j++){
        // DO NOTHING
    }
}
long end2 = System.currentTimeMillis();
System.out.println("i++ Zeit2: "+(end2-start2));
i++ Zeit: 4
i++ Zeit2: 2
Also wird da schon das ein oder andere optimiert ;)
 

Fu3L

Top Contributor
Ich hab hier im Forum gelernt, dass System.currentTimeInMillis() eh ungenau ist^^ Nimm doch lieber System.nanoTime(), da sind die Unterschiede auch besser zu sehen^^
Und vllt muss man auch noch an Hotspot denken (deswegen mal die Reihenfolge vertauschen)
 
B

bERt0r

Gast
Bei mir ergibt folgender Code:
Java:
long start = System.currentTimeMillis();
for (int i=0;i<Integer.MAX_VALUE;i++) {
    for(int j=0;j<10;j++){
    	// DO NOTHING
    }
}
long end = System.currentTimeMillis();
System.out.println("i++ Zeit: "+(end-start));
 
long start2 = System.currentTimeMillis();
for (int i=0;i<Integer.MAX_VALUE;i++) {
    for(int j=0;j<10000000;j++){
        // DO NOTHING
    }
}
long end2 = System.currentTimeMillis();
System.out.println("i++ Zeit2: "+(end2-start2));

Also wird da schon das ein oder andere optimiert ;)

Das liegt dann wohl an der verwendeten Java Version, bei mir dauerts nämlich an die 28 sekunden (auf die 2. Schleife hab ich nicht gewartet :))
 

njans

Top Contributor
Java:
 long start=new Date().getTime();
        for (int i=0;i<Integer.MAX_VALUE;i++)
        {
            for(int j=0;j<1;j++){}
        }
        long end=new Date().getTime();
        System.out.println("i++ Zeit: "+(end-start));
        
        start=new Date().getTime();
        for (int i=0;i<Integer.MAX_VALUE;i++)
        {
            for(int j=0;j<10;j++){}
        }
        end=new Date().getTime();
        System.out.println("i++ Zeit: "+(end-start));
Also bei mir ist das als Ergebnis rausgekommen:
Code:
i++ Zeit: 6714
i++ Zeit: 23443

Natürlich erkennt man, dass da was optimiert wird. Dennoch ist java nicht so schlau zu erkennen, dass da eigentlich nichts gemacht wird.
 

turtle

Top Contributor
Java:
		for (int i = 0; i < 100; i++) {
		}
		for (int i=0; i<100; ++i) {
		}

ergibt in javap
Code:
  0:   iconst_0
  1:   istore_1
  2:   goto    8
  5:   iinc    1, 1
  8:   iload_1
  9:   bipush  100
  11:  if_icmplt       5
  
  14:  iconst_0
  15:  istore_1
  16:  goto    22
  19:  iinc    1, 1
  22:  iload_1
  23:  bipush  100
  25:  if_icmplt       19
  28:  return


Ist für mich identische Code
 

Marco13

Top Contributor
@turtle: Jup, das hatte ich auch mal ausporbiert (ich dachte auch, dass es einen Unterschied im Bytecode gäbe, aber javap hat mich eines besseren belehrt).

Der Benchmark ist Unsinn. Ändere mal die Reihenfolge der Messungen, dann schlägt der JIT bei der späteren Messung zu. Dann noch das "-server" flag beim Start übergeben, und es kommen vollkommen andere Werte raus. Sowas kann man kaum vernünftig messen.
 

Ähnliche Java Themen

Neue Themen


Oben