9

I know how to format a double to keep only the available decimal places (DP), up to a certain number of DPs. This example keeps up to 4 DPs.

    double d = 1.0;
    DecimalFormat df = new DecimalFormat("#.####");
    System.out.print(df.format(d)); // returns "1"

    double d = 1.23;
    DecimalFormat df = new DecimalFormat("#.####");
    System.out.print(df.format(d)); // returns "1.23"

    double d = 1.2345678;
    DecimalFormat df = new DecimalFormat("#.####");
    System.out.print(df.format(d)); // returns "1.2346", rounding off: bad!

Now I want whole numbers e.g. 1.0 to return "1" without the unnecessary .0, and the # format character does provide that functionality. But how do I make sure that the number never gets rounded off? Is there any other way other than an arbitrarily long chain of # such as "#.###########################################"?

Or should I just use the default conversion of double to string, and truncate the ".0" if it appears at the end:

    String s = "" + d;
    if(s.substring(s.length()-2).equals(".0")) {
        s=s.substring(0, s.length()-2);
    }

Both ways seems terribly clumsy.

Jean-François Corbett
  • 37,420
  • 30
  • 139
  • 188

3 Answers3

16

I use the following

double d =
String s = (long) d == d ? "" + (long) d : "" + d; 

if you need Double instead for double. (Personally I would avoid using the wrapper if you can)

Double d =
String s = d.longValue() == d ? "" + d.longValue() : "" + d; 
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 2
    even if the compiler may optimize it avay I believe it is better style to use String.valueOf(x) instead of "" + x – rurouni Jan 05 '12 at 10:59
  • @rurouni Many would agree with you. However, I prefer simpler code because its faster to read and write, saving you time all round. If performance is an issue, I still wouldn't use valueOf as it creates objects. – Peter Lawrey Jan 05 '12 at 11:07
  • 2
    @peter: "" + d would also call String.valueOf() internally. It will be converted to an equivalent of "new StringBuilder().append("").append(String.valueOf(d)).toString()" createing many more objects. – rurouni Jan 05 '12 at 11:12
  • +1 Thanks. I just realized that I meant `Double` instead of `double`. So I guess I just have to do `(long) (double) d` instead of just `(long) d` (which doesn't compile). – Jean-François Corbett Jan 05 '12 at 11:31
  • @rurouni As I have found here http://vanillajava.blogspot.com/2012/01/stringvalueofint-vs-int.html Using String.valueOf save the computer about 0.014 micro-seconds, however using `"" +` will save *you* far, far more. – Peter Lawrey Jan 05 '12 at 11:31
  • @Jean-FrançoisCorbett I have updated my answer for `Double` – Peter Lawrey Jan 05 '12 at 11:33
  • Thanks. I use the `Double` wrapper because I wanted to include these numbers in an ArrayList. – Jean-François Corbett Jan 05 '12 at 11:37
  • @Jean-FrançoisCorbett You might like to try TDoubleArrayList http://trove4j.sourceforge.net/javadocs/gnu/trove/list/array/TDoubleArrayList.html – Peter Lawrey Jan 05 '12 at 11:39
0

By default the rounding mode is Up for DecimalFormat. You can set different rounding format as per your requiremnet using setRoundingMode() method

Sample Code to set Rounding mode

double d = 1.2345678;
        DecimalFormat df = new DecimalFormat("#.####");
        df.setRoundingMode(RoundingMode.DOWN);
        System.out.print(df.format(d));//result 1.2345 because of rounding down
Sunil Kumar Sahoo
  • 53,011
  • 55
  • 178
  • 243
  • "how do I make sure that the number never gets rounded" – Jean-François Corbett Jan 05 '12 at 10:57
  • @Jean-FrançoisCorbett: you cannot unless you use binary or any base 2^n number system (e.g. octal or hexadecimal) – rurouni Jan 05 '12 at 11:14
  • Sure, I know about floating point arithmetic, but that's not the point of the question. How do I make sure the string representation of the number doesn't get rounded to something else than `"" + d`? This answer *explicitly* rounds it which is the exact opposite of what I asked. – Jean-François Corbett Jan 05 '12 at 11:34
-1

You could use Double.doubleToLongBits() and extract the exponent and mantissa. From api doc:

Bit 63 (the bit that is selected by the mask 0x8000000000000000L) represents the sign of the floating-point number. Bits 62-52 (the bits that are selected by the mask 0x7ff0000000000000L) represent the exponent. Bits 51-0 (the bits that are selected by the mask 0x000fffffffffffffL) represent the significand (sometimes called the mantissa) of the floating-point number.

The exponent can be used to determine the number of significant digits, but you will always have to round at some point as some binary doulbe values will be endless in decimal.

For a binary representation you could simply use the mantissa and put the decimal dot at the right position (padding with zeros if necessary.

rurouni
  • 2,315
  • 1
  • 19
  • 27
  • Most non integer decimal values cannot be represented as binary number, e.g. 0.1. so it will be approximated to 0.10000000000000000000001 or similar. Maybe you should think about how big the error of the shown representation can be (or how many significant digis are left in the previous calculation) – rurouni Jan 05 '12 at 10:56
  • Sorry, I missed the question was just regarding integer numbers, but I will leave it in case someone can use it ;-) – rurouni Jan 05 '12 at 11:01