title: Is it sufficient to convert a double to a BigDecimal just before addition to retain original precision?
body: <p>We are solving a numeric precision related bug. Our system collects some numbers and spits their sum.
  The issue is that the <strong>system does not retain the numeric precision,</strong> e.g. 300.7 + 400.9 = 701.599..., while expected result would be 701.6. The precision is supposed to adapt to the input values so <strong>we cannot just round results to fixed precision.</strong></p>
  
  <p>The problem is obvious, we use double for the values and addition accumulates the error from the binary representation of the decimal value.</p>
  
  <p>The path of the data is following:</p>
  
  <ol>
  <li>XML file, type xsd:decimal</li>
  <li>Parse into a java primitive double. Its 15 decimal places should be enough, we expect values no longer than 10 digits total, 5 fraction digits.</li>
  <li>Store into <a href="https://dev.mysql.com/doc/refman/5.5/en/floating-point-types.html" rel="nofollow noreferrer">DB MySql 5.5, type double</a></li>
  <li>Load via Hibernate into a JPA entity, i.e. still primitive double</li>
  <li>Sum bunch of these values</li>
  <li>Print the sum into another XML file</li>
  </ol>
  
  <p>Now, I assume the optimal solution would be converting everything to a decimal format. Unsurprisingly, there is a pressure to go with the cheapest solution. It turns out that converting doubles to <a href="https://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html" rel="nofollow noreferrer">BigDecimal</a> just before adding a couple of numbers works in case B in following example:</p>
  
  <pre><code>import java.math.BigDecimal;
  
  public class Arithmetic {
      public static void main(String[] args) {
          double a = 0.3;
          double b = -0.2;
          // A
          System.out.println(a + b);//0.09999999999999998
          // B
          System.out.println(BigDecimal.valueOf(a).add(BigDecimal.valueOf(b)));//0.1
          // C
          System.out.println(new BigDecimal(a).add(new BigDecimal(b)));//0.099999999999999977795539507496869191527366638183593750
      }
  }
  </code></pre>
  
  <p>More about this:
  <a href="https://stackoverflow.com/questions/8073912/why-do-we-need-to-convert-the-double-into-a-string-before-we-can-convert-it-int">Why do we need to convert the double into a string, before we can convert it into a BigDecimal?</a>
  <a href="https://stackoverflow.com/questions/12218515/unpredictability-of-the-bigdecimaldouble-constructor">Unpredictability of the BigDecimal(double) constructor</a></p>
  
  <p>I am worried that such a workaround would be a ticking bomb.
  First, I am not so sure that this arithmetic is bullet proof for all cases.
  Second, there is still some risk that someone in the future might implement some changes and change B to C, because this pitfall is far from obvious and even a unit test may fail to reveal the bug.</p>
  
  <p>I would be willing to live with the second point but the question is: Would this workaround provide correct results? Could there be a case where somehow</p>
  
  <pre><code>Double.valueOf("12345.12345").toString().equals("12345.12345")
  </code></pre>
  
  <p>is false? Given that Double.toString, according to javadoc, prints just the digits needed to uniquely represent underlying double value, so when parsed again, it gives the same double value? Isn't that sufficient for this use case where I only need to add the numbers and print the sum with this magical <a href="https://docs.oracle.com/javase/7/docs/api/java/lang/Double.html#toString(double)" rel="nofollow noreferrer">Double.toString(Double d)</a> method? To be clear, I do prefer what I consider the <em>clean solution</em>, using BigDecimal everywhere, but I am kind of short of arguments to sell it, by which I mean ideally an example where conversion to BigDecimal before addition fails to do the job described above.</p>