H
hüteüberhüte
Gast
Frage steht schon da. Gibt es einen Unterschied zwischen diesen Vergleichsoperatoren? Ist es evtl. sogar typabhängig?
a<3
3>a
public static void main(String[] args) {
Random r = new Random();
int i = r.nextInt();
int j = r.nextInt();
int k = -1;
long t1 = System.nanoTime();
if (i < j) {
k = 0;
}
long t2 = System.nanoTime();
if (i <= j) {
k = 1;
}
long t3 = System.nanoTime();
if (i == j) {
k = 2;
}
long t4 = System.nanoTime();
if (i > j) {
k = 3;
}
long t5 = System.nanoTime();
if (i >= j) {
k = 4;
}
long t6 = System.nanoTime();
System.out.println(k);
System.out.println(t2 - t1 + " ns");
System.out.println(t3 - t2 + " ns");
System.out.println(t4 - t3 + " ns");
System.out.println(t5 - t4 + " ns");
System.out.println(t6 - t5 + " ns");
}
1
0 ns
425 ns
0 ns
425 ns
0 ns
public static void main(String[] args) {
Random r = new Random();
int i = r.nextInt();
int j = r.nextInt();
long t1 = System.nanoTime();
boolean b1 = i < j;
long t2 = System.nanoTime();
boolean b2 = i <= j;
long t3 = System.nanoTime();
boolean b3 = i == j;
long t4 = System.nanoTime();
boolean b4 = i > j;
long t5 = System.nanoTime();
boolean b5 = i >= j;
long t6 = System.nanoTime();
System.out.println(b1);
System.out.println(b2);
System.out.println(b3);
System.out.println(b4);
System.out.println(b5);
System.out.println(t2 - t1 + " ns");
System.out.println(t3 - t2 + " ns");
System.out.println(t4 - t3 + " ns");
System.out.println(t5 - t4 + " ns");
System.out.println(t6 - t5 + " ns");
}
true
true
false
false
false
0 ns
424 ns
0 ns
425 ns
0 ns
true
true
false
false
false
0 ns
425 ns
0 ns
424 ns
0 ns
false
false
false
true
true
424 ns
425 ns
0 ns
425 ns
0 ns
...
Usually, the microprocessor does comparison using electrical gates and not step by step like that. It checks all bits at once.
4
453 ns
453 ns
0 ns
453 ns
0 ns
Hast du den überhaupt eine Anwendung, bei der es auf solche Zahlen ankommt? Oder worauf möchtest du mit diesem Thread hinaus? - So á la: In 2 Milliarden Jahren verbrennt unsere Sonne ^^
i < 5
i <= 4
i != 5
Man kann ja oft schreiben:oderCode:i < 5
oderCode:i <= 4
, ohne einen semantischen Unterschied zu erhalten.Code:i != 5
class Inequalities
{
public static void main(String args[])
{
int x = 1;
int y = 2;
boolean b0 = x < y;
boolean b1 = x <= y;
boolean b2 = x ==y;
boolean b3 = x >= y;
boolean b4 = x > y;
}
}
public static void main(java.lang.String[]);
Code:
0: iconst_1
1: istore_1
2: iconst_2
3: istore_2
4: iload_1
5: iload_2
6: if_icmpge 13
9: iconst_1
10: goto 14
13: iconst_0
14: istore_3
15: iload_1
16: iload_2
17: if_icmpgt 24
20: iconst_1
21: goto 25
24: iconst_0
25: istore 4
27: iload_1
28: iload_2
29: if_icmpne 36
32: iconst_1
33: goto 37
36: iconst_0
37: istore 5
39: iload_1
40: iload_2
41: if_icmplt 48
44: iconst_1
45: goto 49
48: iconst_0
49: istore 6
51: iload_1
52: iload_2
53: if_icmple 60
56: iconst_1
57: goto 61
60: iconst_0
61: istore 7
63: return
}
Diese Zeitmessungen... Hm... ich bin mir nicht sicher, ob das noch ein Auswalzen des Sarkasmus aus der ersten Antwort ist, aber ... man muss damit rechnen, dass nicht: Diese Messungen sind gröbster Unfug. Man könnte viel spekulieren (btw. diese ~400ns sind eben die Timerauflösung auf Windows - auf Linux wären diese Werte AFAIK <100, aber aussagen würden sie trotzdem nichts...)
long t1 = System.nanoTime();
if (i < j) {
k = 0;
}
long t2 = System.nanoTime();
if (i <= j) {
k = 1;
}
...
@Marco
Ich weis zwar nicht warum du immer und immer wieder darauf rumhackst das die Timer-Auflösung der VM unter Windows zu viel langsamer wäre als unter Unix. Es kommt grundsätzlich auf den Hardware-Echtzeit-Systemtaktgeber und die CPU an wie präziese dieser läuft. Und spätestens auf allen Schichten über dem HAL nehmen sich Windows und Unix nichts mehr. Auch hatte ich mal ein Sample mit System.nanoTime() gepostet was deutlich gezeigt hat das die Auflösung unter Win7 Ulti x64 mit Oracle VM 7u5 auf einem Pentium4 531HT deutlich genauer ist als die von dir immer so schlecht geredeten mehreren Millisekunden. Und selbst wenn der Unix-Kernel diesen Wert öfter vom System abfragt und diesen auch irgendwie schneller in die VM bekommt und man dadurch unter Unix wirklich genauere Messergebnisse bekommen würde ... meinst du wirklich das es einen so gewaltigen Unterschied macht ob ich bei einem nichts-sagenden Mikro-Benchmark 100ns oder 150ns als Wert bekomme ? Aussagekraft hat das immer noch nicht.
Nicht jede Darstellung von Humor ist trollenbygones hat also getrollt? Und jeder hat ihm gedankt! =)
bygones hat also getrollt? Und jeder hat ihm gedankt! =)
So nebenbei:
Abgesehen von der Sinnfreiheit, 1 einzelnen Befehl messen zu wollen.
So ein Code ist ja auch aus anderen Gründen völlig ungeeignet als Benchmark.
Wenn eine Bedingung erfüllt wird, dann wird zusätzlicher Code ausgeführt, wenn nicht, dann wird weniger getan.
<
int i = -1;
int j = 0;
int c = 0;
long t1 = System.nanoTime();
for (int k = 0; k < 10000; k++) {
if (i < j) {
c++;
} else {
c++;
}
}
long t2 = System.nanoTime();
for (int k = 0; k < 10000; k++) {
if (i <= j) {
c++;
} else {
c++;
}
}
long t3 = System.nanoTime();
for (int k = 0; k < 10000; k++) {
if (i == j) {
c++;
} else {
c++;
}
}
long t4 = System.nanoTime();
for (int k = 0; k < 10000; k++) {
if (i > j) {
c++;
} else {
c++;
}
}
long t5 = System.nanoTime();
for (int k = 0; k < 10000; k++) {
if (i >= j) {
c++;
} else {
c++;
}
}
long t6 = System.nanoTime();
System.out.println(c);
System.out.println(t2 - t1 + " ns");
System.out.println(t3 - t2 + " ns");
System.out.println(t4 - t3 + " ns");
System.out.println(t5 - t4 + " ns");
System.out.println(t6 - t5 + " ns");
50000
351232 ns
332120 ns
435748 ns
439995 ns
444243 ns
int i = 0;
int j = -1;
50000
440844 ns
425981 ns
431926 ns
352930 ns
344437 ns
==
-1 < 0
-1 <= 0
-1 > 0
-1 >= 0
0 < -1
0 <= -1
0 > -1
0 >= -1
==
Nicht nur kann, sondern auch tut. Soweit ich weis "interpretiert" HotSpot den ByteCode ein mal vor der ersten Ausführung um ihn umzukompilieren und anschliessend nur noch um das erste Kompilat zu optimieren. Wär schön, wenn alle Prozessoren so arbeiten würden, wie dieser virtuelle.Du solltest daran denken, dass der HotSpot Bytecode in nativen Code umkompilieren kann.
Mit der "Server VM" wird aggressiv vom Hotspot/JIT optimiert, mit der "Client VM" so gut wie gar nicht (aber was heisst das schon genau?)
Die Server VM gibt es unter Linux per default mit dem JDK, unter Windows gibt es sie nur mit JDK um dem Parameter [c]-server[/c], ein [c]java -version[/c], [c]java -server -version[/c] und [c]java -client -version[/c] zeigen einem welche VM Variante benutzt wird.
java version "1.7.0_05"
Java(TM) SE Runtime Environment (build 1.7.0_05-b05)
Java HotSpot(TM) 64-Bit Server VM (build 23.1-b03, mixed mode)
-server
nanoStart=System.nanoTime();
for (int i=0;i<runs;i++)
{
f=a<b;
}
nanoDist=System.nanoTime()-nanoStart;
System.out.println("< mit a<b: "+nanoDist+" ns");
< mit a<b: 17195691 ns
< mit a==b: 20180847 ns
< mit a>b: 23380137 ns
<= mit a<b: 13561779 ns
<= mit a==b: 13317335 ns
<= mit a>b: 20400847 ns
== mit a<b: 20270803 ns
== mit a==b: 13471824 ns
== mit a>b: 20068891 ns
!= mit a<b: 13466935 ns
!= mit a==b: 20183780 ns
!= mit a>b: 13967069 ns
-----------------------------------
< mit a<b: 17219647 ns
< mit a==b: 20144669 ns
< mit a>b: 20432625 ns
<= mit a<b: 14058002 ns
<= mit a==b: 13589158 ns
<= mit a>b: 20816403 ns
== mit a<b: 20324091 ns
== mit a==b: 14433469 ns
== mit a>b: 20548003 ns
!= mit a<b: 13924046 ns
!= mit a==b: 20130491 ns
!= mit a>b: 13648802 ns
----------------------------------
< mit a<b: 17446002 ns
< mit a==b: 20230713 ns
< mit a>b: 20631114 ns
<= mit a<b: 13563735 ns
<= mit a==b: 13622401 ns
<= mit a>b: 20995824 ns
== mit a<b: 20325070 ns
== mit a==b: 13549069 ns
== mit a>b: 20250269 ns
!= mit a<b: 13442491 ns
!= mit a==b: 20348536 ns
!= mit a>b: 14292668 ns
<= mit a==b: 13317335 ns 13589158 ns 13622401 ns | 13509631 ns
!= mit a<b: 13466935 ns 13924046 ns 13442491 ns | 13611156 ns
<= mit a<b: 13561779 ns 14058002 ns 13563735 ns | 13727838 ns
== mit a==b: 13471824 ns 14433469 ns 13549069 ns | 13818120 ns
!= mit a>b: 13967069 ns 13648802 ns 14292668 ns | 13969513 ns
== mit a>b: 20068891 ns 20548003 ns 20250269 ns | 14268388 ns
< mit a<b: 17195691 ns 17219647 ns 17446002 ns | 17287113 ns
< mit a==b: 20180847 ns 20144669 ns 20230713 ns | 20185410 ns
!= mit a==b: 20183780 ns 20130491 ns 20348536 ns | 20220936 ns
== mit a<b: 20270803 ns 20324091 ns 20325070 ns | 20306655 ns
<= mit a>b: 20400847 ns 20816403 ns 20995824 ns | 20737691 ns
< mit a>b: 23380137 ns 20432625 ns 20631114 ns | 21381292 ns
Genau das letztere hatte ich ja auch gesagt. Ich finde zwar nicht, dass ich auf irgendwas "rumhacke", aber dass Windows, abhängig von der Version, unterschiedliche Timerauflösungen hat, die insbesondere nicht "eine Nanosekunde" sind, sollte man sich bewußt machen, wenn man irgendwelche Timing-Tests schreibt. Im Web gibt es genügend Resourcen dazu. Bei manchen kann man davon ausgehen, dass sie sehr profund sind, und von Leuten stammen, die genau wissen, was sie tun und was man beachten muss. Andere stammen aus irgendwelchen Foren, wo anonyme Gäste sowas posten wie "Ich hab' mal was gemessen, und rausgefunden, dass alle anderen etwas falsch gemacht haben", .... ja, who cares. Ich werde auf die Tatsache, dass die Timer-Auflösung nicht "1 Millisekunde" oder gar "1 Nanosekunde" ist, und sie auf Windows (bei den meisten Versionen) im Bereich von mehreren Millisekunden liegt, so lange hinweisen, wie Leute versuchen, die Ausführungzeit einer einzelnen if-Abfrage durch zwei einschließende Aufrufe zu currentTimeMillis oder nanoTime zu messen. Vermutlich also für immer
int i = 0;
int j = 0;
boolean b = false;
long t1 = System.nanoTime();
for (int k = 0; k < 100000; k++) {
b = i < j;
}
long t2 = System.nanoTime();
for (int k = 0; k < 100000; k++) {
b = i <= j;
}
long t3 = System.nanoTime();
for (int k = 0; k < 100000; k++) {
b = i == j;
}
long t4 = System.nanoTime();
for (int k = 0; k < 100000; k++) {
b = i > j;
}
long t5 = System.nanoTime();
for (int k = 0; k < 100000; k++) {
b = i >= j;
}
long t6 = System.nanoTime();
System.out.println(b);
System.out.println(t2 - t1 + " ns");
System.out.println(t3 - t2 + " ns");
System.out.println(t4 - t3 + " ns");
System.out.println(t5 - t4 + " ns");
System.out.println(t6 - t5 + " ns");
true
6235082 ns
425 ns
0 ns
0 ns
0 ns
Dein Test ist auch immer noch falsch. Immer noch kein Warmup, immer noch statische Werte, ...
Gib es einfach auf, dieser Test ist so oder so total sinnfrei -.-
long t1 = System.nanoTime();
for (int k = 0; k < 100000; k++) {
b = i < j++;
}
long t2 = System.nanoTime();
for (int k = 0; k < 100000; k++) {
b = i <= j++;
}
long t3 = System.nanoTime();
for (int k = 0; k < 100000; k++) {
b = i == j++;
}
long t4 = System.nanoTime();
for (int k = 0; k < 100000; k++) {
b = i > j++;
}
long t5 = System.nanoTime();
for (int k = 0; k < 100000; k++) {
b = i >= j++;
}
long t6 = System.nanoTime();
boolean beq(int a, int b) {
return a == b;
}
boolean bne(int a, int b) {
return a != b;
}
//...
Warum sollte dein Test nicht wegoptimiert werden? Variable b hat eine Zuweisung welche nie gebraucht wird.
System.out.println(b);
Tja... woher will dieser "stupide" HotSpot auch wissen, dass man Dönekens machen will.Dank Inlining wird auch das mit Pech wieder wieder rausoptimiert.