Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p><strong>Summary</strong></p> <p>In Java 6 (and presumably earlier), <code>round(x)</code> is implemented as <code>floor(x+0.5)</code>.<sup>1</sup> This is a specification bug, for precisely this one pathological case.<sup>2</sup> Java 7 no longer mandates this broken implementation.<sup>3</sup></p> <p><strong>The problem</strong></p> <p>0.5+0.49999999999999994 is exactly 1 in double precision:</p> <pre><code>static void print(double d) { System.out.printf("%016x\n", Double.doubleToLongBits(d)); } public static void main(String args[]) { double a = 0.5; double b = 0.49999999999999994; print(a); // 3fe0000000000000 print(b); // 3fdfffffffffffff print(a+b); // 3ff0000000000000 print(1.0); // 3ff0000000000000 } </code></pre> <p>This is because 0.49999999999999994 has a smaller exponent than 0.5, so when they're added, its mantissa is shifted, and the ULP gets bigger.</p> <p><strong>The solution</strong></p> <p>Since Java 7, OpenJDK (for example) implements it thus:<sup>4</sup></p> <pre><code>public static long round(double a) { if (a != 0x1.fffffffffffffp-2) // greatest double value less than 0.5 return (long)floor(a + 0.5d); else return 0; } </code></pre> <hr> <p><sub> 1. <a href="http://docs.oracle.com/javase/6/docs/api/java/lang/Math.html#round%28double%29" rel="noreferrer">http://docs.oracle.com/javase/6/docs/api/java/lang/Math.html#round%28double%29</a> </sub></p> <p><sub> 2. <a href="http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6430675" rel="noreferrer">http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6430675</a> (credits to @SimonNickerson for finding this) </sub></p> <p><sub> 3. <a href="http://docs.oracle.com/javase/7/docs/api/java/lang/Math.html#round%28double%29" rel="noreferrer">http://docs.oracle.com/javase/7/docs/api/java/lang/Math.html#round%28double%29</a> </sub></p> <p><sub> 4. <a href="http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/java/lang/Math.java#Math.round%28double%29" rel="noreferrer">http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/java/lang/Math.java#Math.round%28double%29</a> </sub></p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload