sanity
sanity

Reputation: 35772

How do I make Java format a double like -3.2 rather than -3.1999999999999953?

My app is producing doubles where Double.toString() produces "-3.1999999999999953" - whereas I would expect it to produce "-3.2".

I'm actually getting these doubles from JScience's Amount#getEstimatedValue().

I don't want to set an arbitrary number of digits for precision, since I don't know how many digits will be significant, but I don't want it to produce numbers that end in "99999999.*".

How can I convert Doubles to Strings without this problem?

Upvotes: 8

Views: 846

Answers (3)

Filip Roséen
Filip Roséen

Reputation: 63797

Recommended solution

BigDecimal.valueOf (hisDouble).toPlainString ()

The hack provided later in the last section of this post was the first thing that came to mind when trying to solve OPs question.

Then a friend asked what I was doing and said that OP be better of using BigDecimal and I went into facepalm mode..

But I'll leave the hack in this post so that the world can see how stupid I can be sometimes.


When printing you can use System.out.format.

The snippet below will will round the value of yourDecimal to one decimal and then print the value.

Double yourDouble = -3.1999999999999953;
System.out.format ("%.1f", yourDouble);

output

-3.2

The most stupid hack ever written

  public static String fixDecimal (Double d) {
    String  str = "" + d;
    int    nDot = str.indexOf ('.');

    if (nDot == -1)
      return str;

    for (int i = nDot, j=0, last ='?'; i < str.length (); ++i) {
      j = str.charAt (i) == last ? j+1 : 0;

      if (j > 3)
        return String.format ("%."+(i-nDot-j-1)+"f", d);

      last = str.charAt (i);
    }

    return str;
  }

...

Double[] testcases = {
  3.19999999999953,
  3.145963219488888,
  10.4511111112,
  100000.0
};

for (int i =0; i < testcases.length; ++i)
  System.out.println (
    fixDecimal (testcases[i]) + "\n"
  );

output

3.2
3.1459632195
10.45
100000.0

Upvotes: 7

Sean Patrick Floyd
Sean Patrick Floyd

Reputation: 298898

Use BigDecimal:

System.out.println(BigDecimal.valueOf(-3.2d).toPlainString());

Output:

-3.2

Upvotes: 4

Brian
Brian

Reputation: 6450

You could try

http://docs.oracle.com/javase/1.4.2/docs/api/java/text/DecimalFormat.html

Slightly "heavyweight", but should do the trick. Some example usage at:

DecimalFormat subpattern boundary not working right

Upvotes: 3

Related Questions