JDK-4800959 : Wrong result when multiplying int and double
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 1.4.0
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2003-01-09
  • Updated: 2003-01-09
  • Resolved: 2003-01-09
Related Reports
Duplicate :  
Description
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) 
======================================================================

Comments
WORK AROUND Name: tb29552 Date: 01/09/2003 ###@###.### 2003-01-08 Use any one of the workarounds below: 1) Run the Server VM instead of Client by adding "-server" to the command line. 2) Run the program on a SPARC architecture CPU instead of x86 3) Run in interpreted mode by adding "-Xint" to the command line ======================================================================
11-06-2004

EVALUATION Already fixed in 1.4.2. This is almost certainly the same problem as 4732721. ###@###.### 2003-01-09
09-01-2003