Name: tb29552 Date: 01/09/2003
FULL PRODUCT VERSION :
java version "1.3.0_02"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0_02)
Java HotSpot(TM) Client VM (build 1.3.0_02, mixed mode)
AND
java version "1.4.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-b92)
Java HotSpot(TM) Client VM (build 1.4.0-b92, mixed mode)
FULL OPERATING SYSTEM VERSION :
Windows 2000 SP 3. (Version number: 5.00.2195)
EXTRA RELEVANT SYSTEM CONFIGURATION :
Processor: Pentium 3, 700 MHz.
Problem also appears on a Pentium 4, 2 GHz.
A DESCRIPTION OF THE PROBLEM :
The program multiplies int-values with double-values.
The result of these multiplications are added. Java 1.3
gets the expected result (between 0 and 1). Java 1.4 gets a
result far bigger (over 1.5 million).
REGRESSION. Last worked in version 1.3
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Compile the class Bug.java
2. Run the main-Method of the class (this takes between 3
and 6 minutes on a Pentium 3, 700 MHz).
3.
EXPECTED VERSUS ACTUAL BEHAVIOR :
Expected output for JDK 1.3 & JDK 1.4 (only the lines
starting with "Maximale Rendite:" and "Maximale Rendite
(unnormalisiert)" are relevant:
7 Fonds, maximales Risiko: 0.06
306034358 Iterationen.
Dauer: 390642ms = 6'30.642 min.
====== Ergebnis ======
Maximale Rendite: 0.12969999999999998
Maximale Rendite (nicht normalisiert): 12.969999999999999
Risiko: 0.059980496830219734
===== Aufteilung =====
Fonds Risiko Rendite Prozent
0 0.13 0.12 0.18
1 0.11 0.14 0.33
2 0.08 0.05 0.0
3 0.09 0.07 0.13
4 0.14 0.15 0.24
5 0.18 0.14 0.12
6 0.04 0.05 0.0
Actual output (JDK 1.3):
Maximale Rendite: 0.12969999999999998
Maximale Rendite (nicht normalisiert): 12.969999999999999
Actual output (JDK 1.4):
Maximale Rendite: 1505176.4075000002
Maximale Rendite (nicht normalisiert): 2.8248866509E8
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
public class Bug {;
public static void main(String[] args) {
double[] risiko = new double[] { 0.13, 0.11, 0.08, 0.09, 0.14, 0.18, 0.04 };
double[] rendite = new double[] { 0.12, 0.14, 0.05, 0.07, 0.15, 0.14,
0.05 };
Bug.findOptimum(risiko, rendite, 0.06);
}
protected static boolean findOptimum(double[] risiko, double[] rendite,
double anleger_risiko) {
if (risiko == null || rendite == null || risiko.length != 7 ||
rendite.length != 7) return false;
int[] x = new int[7];
int[] max_rendite_x = new int[7];
int gesamt = 100;
double max_rendite = -100.0, max_rendite_risiko = 0.0, rendite_neu;
double max_rendite_unnormal = -100.0, rendite_unnormal_neu;
double risiko_p;
int iterator = 0;
long begin = System.currentTimeMillis();
for (x[0] = 0; x[0] <= gesamt; x[0] += 1) {
if (x[0] != 0 && x[0] < 5) x[0] = 5;
for (x[1] = 0; x[1] <= gesamt - x[0]; x[1] += 1) {
if (x[1] != 0 && x[1] < 5) x[1] = 5;
for (x[2] = 0; x[2] <= gesamt - x[0] - x[1]; x[2] += 1) {
if (x[2] != 0 && x[2] < 5) x[2] = 5;
for (x[3] = 0; x[3] <= gesamt - x[0] - x[1] - x[2]; x[3] += 1) {
if (x[3] != 0 && x[3] < 5) x[3] = 5;
for (x[4] = 0; x[4] <= gesamt - x[0] - x[1] - x[2] - x[3]; x[4] +=
1) {
if (x[4] != 0 && x[4] < 5) x[4] = 5;
for (x[5] = 0; x[5] <= gesamt - x[0] - x[1] - x[2] - x[3] - x[4];
x[5] += 1) {
if (x[5] != 0 && x[5] < 5) x[5] = 5;
x[6] = gesamt - (x[0] + x[1] + x[2] + x[3] + x[4] + x[5]);
if (x[6] < 0) break;
else if (x[6] < 5) {
x[5] += x[6];
x[6] = 0;
}
iterator++;
risiko_p = (risiko[0] * risiko[0] * x[0] * x[0]) +
(risiko[1] * risiko[1] * x[1] * x[1]) +
(risiko[2] * risiko[2] * x[2] * x[2]) +
(risiko[3] * risiko[3] * x[3] * x[3]) +
(risiko[4] * risiko[4] * x[4] * x[4]) +
(risiko[5] * risiko[5] * x[5] * x[5]) +
(risiko[6] * risiko[6] * x[6] * x[6]);
if (anleger_risiko * anleger_risiko * gesamt * gesamt >=
risiko_p) {
// Rendite berechnen
rendite_neu = (x[0] * rendite[0] +
x[1] * rendite[1] +
x[2] * rendite[2] +
x[3] * rendite[3] +
x[4] * rendite[4] +
x[5] * rendite[5] +
x[6] * rendite[6]) / ((double) gesamt);
if (rendite_neu > max_rendite) {
max_rendite_unnormal = x[0] * rendite[0] +
x[1] * rendite[1] +
x[2] * rendite[2] +
x[3] * rendite[3] +
x[4] * rendite[4] +
x[5] * rendite[5] +
x[6] * rendite[6];
System.arraycopy(x, 0, max_rendite_x, 0, x.length);
max_rendite_risiko = Math.sqrt(risiko_p / (gesamt *
gesamt));
max_rendite = rendite_neu;
}
}
}
}
}
}
}
}
long ende = System.currentTimeMillis();
System.out.println("\n7 Fonds, maximales Risiko: " + anleger_risiko);
System.out.println(iterator + " Iterationen.");
System.out.println("Dauer: " + (ende - begin) + "ms = " + ((ende - begin) /
60000) + "'" + (((ende - begin) % 60000) / 1000) + "." + (((ende - begin) %
60000) % 1000) + " min.");
System.out.println("\n====== Ergebnis ======");
if (max_rendite > 0) {
System.out.println("Maximale Rendite: " + max_rendite);
System.out.println("Maximale Rendite (nicht normalisiert): " +
max_rendite_unnormal);
System.out.println("Risiko: " + max_rendite_risiko);
System.out.println("\n===== Aufteilung =====");
System.out.println("Fonds\tRisiko\tRendite\tProzent");
for (int j = 0; j < max_rendite_x.length; j++) {
System.out.println(j + "\t" + risiko[j] + "\t" + rendite[j] + "\t" +
(max_rendite_x[j] / ((double) gesamt)));
}
}
else {
System.out.println("Kein Ergebnis gefunden!");
}
return true;
}
}
---------- END SOURCE ----------
CUSTOMER WORKAROUND :
Using JDK 1.3. instead of JDK 1.4.
(Review ID: 178527)
======================================================================