Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4860749

REGRESSION: Wrong double calculation result for Pi (Windows only)

    Details

    • Subcomponent:
      2d
    • Resolved In Build:
      b23
    • CPU:
      x86
    • OS:
      windows_2000

      Backports

        Description



        Name: rmT116609 Date: 05/08/2003


        FULL PRODUCT VERSION :
        D:\Temp>"c:\Program Files\Java\j2re1.4.2\bin\java" -version
        java version "1.4.2-beta"
        Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2-beta-b19)
        Java HotSpot(TM) Client VM (build 1.4.2-beta-b19, mixed mode)

        FULL OS VERSION :
        Microsoft Windows 2000 [Version 5.00.2195]

        A DESCRIPTION OF THE PROBLEM :
        On this small benchmark application, the Pi calculation gives a wrong result, when running on JDK 1.4.2 Beta.

        This does not occur with other JDK versions or when extracting the Pi calculation code from the program. So I suppose it depends on the context (GC running before...). Using strictfp does not change the behavior.

        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        Run the Zjb program

        java -cp . Zjb

        EXPECTED VERSUS ACTUAL BEHAVIOR :
        With other JDK: Pi=3.141591698659554

        With JDK 1.4.2 Beta: Pi=3.1413934230804443

        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------

        import java.awt.BorderLayout;
        import java.awt.Button;
        import java.awt.Color;
        import java.awt.Dialog;
        import java.awt.Dimension;
        import java.awt.FlowLayout;
        import java.awt.Frame;
        import java.awt.Graphics;
        import java.awt.GridLayout;
        import java.awt.Label;
        import java.awt.List;
        import java.awt.Panel;
        import java.awt.TextField;
        import java.awt.Toolkit;

        import java.awt.event.ActionEvent;
        import java.awt.event.ActionListener;
        import java.awt.event.WindowAdapter;
        import java.awt.event.WindowEvent;
        import java.io.BufferedInputStream;
        import java.io.BufferedOutputStream;
        import java.io.File;
        import java.io.FileInputStream;
        import java.io.FileOutputStream;
        import java.io.IOException;
        import java.math.BigInteger;


        /**
         * Zjb: Zaurus Java Bechmark
         * @author GenePi
         */
        class Zjb
        extends Frame
        {
        static Zjb _mainWindow;


        /**
        * Number of benchmark runs.
        */
        private final TextField _runs;


        /**
        * Results list
        */
        private final List _results;


        /**
        * Wait, program is thinking...
        */
        private final Label _wait;


        /**
        * Start button
        */
        private final Button _start;


        /**
        * Benchmark running
        */
        private volatile boolean _running = false;


        /**
        * Layout the main window.
        **/
        Zjb()
        {
        super("Zaurus java benchmark 1.0");

        setLayout(new BorderLayout());

        // Input fields
        Panel top = new Panel(new GridLayout(1, 0));
        top.add(new Label("Number of runs"));
        _runs = new TextField("1");
        top.add(_runs);

        add(top, BorderLayout.NORTH);

        // Results list
        _results = new List();
        add(_results, BorderLayout.CENTER);

        // Start button
        final Panel bottom = new Panel(new FlowLayout(FlowLayout.RIGHT));
        _wait = new Label();
        bottom.add(_wait);
        _start = new Button("Start");
        _start.addActionListener(new ActionListener()
        {
        public void actionPerformed(final ActionEvent evt)
        {
        if (!_running)
        {
        // Clear previous results and start benchmark.
        _results.clear();
        _start.setLabel("Stop");
        _wait.setText("Running... ");
        bottom.validate();
        _running = true;
        }
        else
        {
        _start.setLabel("Start");
        _wait.setText("");
        _running = false;
        }
        }
        });
        bottom.add(_start);

        // Quit button
        final Button quit = new Button("Quit");
        quit.addActionListener(new ActionListener()
        {
        public void actionPerformed(final ActionEvent evt)
        {
        System.exit(0);
        }
        });
        bottom.add(quit);

        add(bottom, BorderLayout.SOUTH);

        // Exit when main window closes
        addWindowListener(new WindowAdapter()
        {
        public void windowClosing(final WindowEvent evt)
        {
        System.exit(0);
        }
        });

        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
        setSize(dim);
        validate();
        }



        /**
        * The benchmarks
        *
        * @param runs Number of runs
        */
        private static void runBenchmarks(final int runs)
        {
        long start;
        long end;
        long totalStart;
        long totalEnd;

        // Integer arithmetic
        start = System.currentTimeMillis();
        totalStart = start;
        int resultInt = 0;
        for (int i = 0; i < runs; i++)
        {
        resultInt = ackerman(3, 9);
        // resultInt = ackerman(3, 7);
        }
        end = System.currentTimeMillis();
        _mainWindow._results.add("Integer arithmetic: " + ((end - start) / 1000.0) + " s [Ack(3,9)=" + resultInt + "]");

        if (!_mainWindow._running)
        {
        return;
        }


        // Float and double
        start = System.currentTimeMillis();
        double resultDouble = 0.0;
        for (int i = 0; i < runs; i++)
        {
        resultDouble = 0.0;
        for (int j = 1; j < 1000000; j++)
        {
        resultDouble += 1.0 / ((double) j * (double) j);
        }
        resultDouble = Math.sqrt(resultDouble * 6.0);
        }
        end = System.currentTimeMillis();
        _mainWindow._results.add("Double arithmetic: " + ((end - start) / 1000.0) + " s [Pi=" + resultDouble + "]");

        if (!_mainWindow._running)
        {
        return;
        }


        // Big operations
        start = System.currentTimeMillis();
        BigInteger resultBig = new BigInteger("1");
        for (int i = 0; i < runs; i++)
        {
        resultBig = fact(3000);
        }
        end = System.currentTimeMillis();
        _mainWindow._results.add("Infinite arithmetic: " + ((end - start) / 1000.0) + " s [3000!=" + resultBig.toString().substring(1, 20) + "...]");

        if (!_mainWindow._running)
        {
        return;
        }


        // Strings
        start = System.currentTimeMillis();
        String resultString = null;
        for (int i = 0; i < runs; i++)
        {
        final String alphabet = " qwertyuioplkjhgfdsazxcvbnm0789456123./*";
        StringBuffer buf = new StringBuffer();
        for (int j = 0; j < 100000; j++)
        {
        int pos = j % alphabet.length();
        buf.append(alphabet.substring(pos, pos + 1));
        }
        resultString = buf.toString();
        }
        end = System.currentTimeMillis();
        _mainWindow._results.add("Strings: " + ((end - start) / 1000.0) + " s [" + resultString.substring(1, 20) + "...]");

        if (!_mainWindow._running)
        {
        return;
        }


        // Drawing
        start = System.currentTimeMillis();
        for (int i = 0; i < runs; i++)
        {
        final int size = 200;
        Dialog dialog = new Dialog(_mainWindow, "Drawing...", true);
        dialog.add(new TestPanel(dialog));
        dialog.setSize(size, size);
        dialog.show();
        }
        end = System.currentTimeMillis();
        _mainWindow._results.add("Drawing: " + ((end - start) / 1000.0) + " s");

        if (!_mainWindow._running)
        {
        return;
        }


        // File copy
        start = System.currentTimeMillis();
        String resultIO = "OK";
        loopIO:
        for (int i = 0; i < runs; i++)
        {
        final String tempName = "/tmp/Zjb.tmp";
        try
        {
        BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(tempName));
        for (int j = 0; j < 1000000; j++)
        {
        out.write((byte) j);
        }
        out.close();

        BufferedInputStream in = new BufferedInputStream(new FileInputStream(tempName));
        for (int j = 0; j < 1000000; j++)
        {
        int r = in.read();
        if ((byte) r != (byte) j)
        {
        resultIO = "Failed";
        System.err.println("Content mismatch at " + j);
        break loopIO;
        }
        }
        in.close();

        new File(tempName).delete();
        }
        catch(IOException ioe)
        {
        resultIO = "Failed";
        System.err.println(ioe);
        break loopIO;
        }
        }
        end = System.currentTimeMillis();
        _mainWindow._results.add("Files I/O: " + ((end - start) / 1000.0) + " s [1MB written/read/deleted: " + resultIO + "]");

        totalEnd = end;
        _mainWindow._results.add("");
        _mainWindow._results.add("Total: " + ((totalEnd - totalStart) / 1000.0) + " s");
        }


        /**
        * Utility functions: Ackerman function
        *
        * @param m
        * @param n
        */
        private static int ackerman(final int m, final int n)
        {
        if (m == 0)
        {
        return (n + 1);
        }
        else if (n == 0)
        {
        return (ackerman(m - 1, 1));
        }
        else
        {
        return ackerman(m - 1, ackerman(m, (n - 1)));
        }
        }


        /**
        * Factorial of big numbers.
        *
        * @param n
        * @return
        */
        private static BigInteger fact(final int n)
        {
        final BigInteger one = new BigInteger("1");
        BigInteger num = new BigInteger("1");
        BigInteger fact = new BigInteger("1");
        for (int i = 2; i <= n; i++)
        {
        num = num.add(one);
        fact = fact.multiply(num);
        }

        return fact;
        }


        /**
        * Benchmark entry point.
        *
        * @param args Command line arguments
        */
        public static void main(String[] args)
        {
        _mainWindow = new Zjb();
        _mainWindow.show();

        synchronized (Zjb.class)
        {
        while (true)
        {
        try
        {
        Zjb.class.wait(500L);
        }
        catch (InterruptedException ie)
        {
        // Wake
        }
        if (_mainWindow._running)
        {
        try
        {
        runBenchmarks(Integer.parseInt(_mainWindow._runs.getText()));
        }
        catch (NumberFormatException nfe)
        {
        _mainWindow._runs.setText("1");
        runBenchmarks(1);
        }
        _mainWindow._running = false;
        _mainWindow._start.setLabel("Start");
        _mainWindow._wait.setText("");
        }
        }
        }
        }
        }


        class TestPanel
        extends Panel
        {
        /**
        * The dialog containing the panel.
        */
        private final Dialog _dialog;


        TestPanel(final Dialog dialog)
        {
        _dialog = dialog;
        }


        public void paint(final Graphics g)
        {
        Dimension dim = getSize();
        g.setColor(Color.white);
        g.fillRect(0, 0, dim.width, dim.height);
        for (int i = 0; i < 1000; i++)
        {
        Color color = new Color((int) (Math.random() * Integer.MAX_VALUE));
        int x = (int) (Math.random() * dim.width);
        int y = (int) (Math.random() * dim.height);
        int width = (int) (Math.random() * dim.width);
        int height = (int) (Math.random() * dim.height);
        g.setColor(color);
        g.fillRect(x, y, width, height);
        }

        g.setColor(Color.white);
        g.fillRect(0, 0, dim.width, dim.height);
        for (int i = 0; i < 1000; i++)
        {
        Color color = new Color((int) (Math.random() * Integer.MAX_VALUE));
        int x = (int) (Math.random() * dim.width);
        int y = (int) (Math.random() * dim.height);
        int width = (int) (Math.random() * dim.width);
        int height = (int) (Math.random() * dim.height);
        g.setColor(color);
        g.fillOval(x, y, width, height);
        }


        // Hide dialog when finished
        _dialog.hide();
        }
        }
        ---------- END SOURCE ----------

        (Review ID: 184686)
        ======================================================================

          Attachments

            Issue Links

              Activity

                People

                • Assignee:
                  chaasesunw Chet Haase (Inactive)
                  Reporter:
                  rmandalasunw Ranjith Mandala (Inactive)
                • Votes:
                  0 Vote for this issue
                  Watchers:
                  2 Start watching this issue

                  Dates

                  • Created:
                    Updated:
                    Resolved:
                    Imported:
                    Indexed: