4

I'm working on a project which requires me to have double values at exactly 2 decimal place. Using some math, I currently have most numbers rounded correctly, except if there are trailing zeros. I want to keep these 0's for results like 0.00 in particular This list is displayed in a TableView, so therefore must be sortable numerically. I'd like the double values to actually be doubles so that it may properly sort.

Is there any way I can keep 2 decimal places without String.format?

Thank you in advance.

user3806226
  • 225
  • 1
  • 6
  • 14

6 Answers6

3

You can use DecimalFormat

DecimalFormat df = new DecimalFormat("#.00"); 

00 = exactly two decimal places.

But this will give to you a String that you can convert again to a double, if you don't want to have this String-conversion check this question to see how it can be achieved using BigDecimal.

IMHO, if this is not for learning pourposes DecimalFormat will be enough for you. True, you will have to use String in some moment of the conversion, but you will only read and store double values and your sorting will be the correct...

Community
  • 1
  • 1
Jordi Castilla
  • 26,609
  • 8
  • 70
  • 109
  • My main concern is that these double values are being displayed in a TableView. The table itself can be sorted by selecting a column--which works fine. The table cells are displaying the double values stored as SimpleDoubleProperty. Rounding to 2 decimal places is working correctly except if there are trailing zeros, so I'm trying to find a way around that. Ex. 2.50 rather than 2.5 – user3806226 May 11 '15 at 12:28
  • So `double-String-double` is what you need – Jordi Castilla May 11 '15 at 13:22
1

This answer expands on the suggestion to use java.math.BigDecimal rather than double.

It is better for this application than double because every two decimal place number is exactly representable in BigDecimal. The rounding from an arbitrary double-representable value down to two decimal places can be easily done according to any of several rounding modes, including the one used for double arithmetic.

On the other hand, it is better than String because the natural sort order is numeric value.

Here is a short demo program illustrating these points:

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class Test {
  public static void main(String[] args) throws Throwable {
    List<BigDecimal> list = new ArrayList<BigDecimal>();
    double[] in = {
        3.5,
        Math.PI,
        -100.123456,
        1e6
    };
    System.out.println("Original doubles: "+Arrays.toString(in));
    for(double d : in){
      list.add(doubleToBigDecimal(d,1));
    }
    System.out.println("Before sorting: " + list);
    Collections.sort(list);
    System.out.println("After sorting: " + list);
  }

  public static BigDecimal doubleToBigDecimal(double in, int places) {
    BigDecimal result = new BigDecimal(in).setScale(2,
        BigDecimal.ROUND_HALF_EVEN);
    return result;
  }
}

Output:

Original doubles: [3.5, 3.141592653589793, -100.123456, 1000000.0]
Before sorting: [3.50, 3.14, -100.12, 1000000.00]
After sorting: [-100.12, 3.14, 3.50, 1000000.00]
Patricia Shanahan
  • 25,849
  • 4
  • 38
  • 75
0

You can use DecimalFormat, Just set format in DecimalFormat's constructor as your required 2dp so:

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

output:

1.23

this code will round the decimal upto to decimal places However it's result will be not upto 2 decimal if value it self is not minimum 2 decimal places. e.g.

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

output:

1.2

as Thisaru Guruge said and Jordi Castilla answer you can use like:

 double d = 1.2;
    DecimalFormat df = new DecimalFormat("#.00");
    System.out.print(df.format(d));

output:

1.20
Sarz
  • 1,970
  • 4
  • 23
  • 43
  • 1
    this will show `0.00` as `0.0`. not `0.00` using `DecimalFormat("0.00")` will do. Reference: http://docs.oracle.com/javase/7/docs/api/java/text/DecimalFormat.html – ThisaruG May 11 '15 at 11:56
0

You can try BigDecimal, or you can simply create your own object that implements the Comparable interface for sorting and has a toString() method that outputs the value formatted to two decimal places.

class TableValue implements Comparable<TableValue> {

    double value;

    public TableValue(double value) {
        this.value = value;

    }

    public int compareTo(TableValue o) {
        return Double.compare(this.value, o.value);
    }


    public String toString() {
        DecimalFormat df = new DecimalFormat("0.00");
        return df.format(value);
    }
}
Robert
  • 39,162
  • 17
  • 99
  • 152
0

Doubles are imprecise, BigDecimal has an extra attribute: its precision.

So new BigDecimal("5.20") would have a precision of 2, whereas double 5.20 * 10000 probably sufficiently deviates from 52000.0.

Mind the avoidable new BigDecimal(5.20) neither knows a precision, neither is precise.

BigDecimal unfortunately has a COBOListic usage.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • If you think BigDecimal is inherently precise, try calculating 1/3 using it. It does have an advantage over double for this case - exact representation of all short decimal fractions. – Patricia Shanahan May 11 '15 at 14:28
0

You can use DecimalFormat class upto how much precision point you want you can set in class constructor suppose you want 2 precision you can set like

Double total= 12.15356789;
DecimalFormat df = new DecimalFormat("##.00");

Format the value using format method

 String dx = df.format(total);

This will return String value of your Double value if you want Double with formatted 2 precision then use below line of code

Double totalVal = Double.valueOf(df.format(total));

This will return you Double value with 2 precision output would be like 12.15

anandchaugule
  • 901
  • 12
  • 20