Formatting Decimal Number

2019-08-08 00:47发布

问题:

I am formatting a decimal number and I have the following criteria to format it:

  • Number should be at most two decimal places (10.1234=>10.12)
  • If there is only one digit after decimal then it will ends up with an extra 0 (10.5=>10.50)
  • Thousand separator will be comma (12345.2345 => 12,345.23)

I have written following logic:

double x = Double.parseDouble(value.toString());
String dec = x % 1 == 0 ?  new java.text.DecimalFormat("###,###.##").format(x) : new java.text.DecimalFormat("###,###.00").format(x);

Now it is printing:

11111111111110.567=>11,111,111,111,110.57
111111111111110.567=>111,111,111,111,110.56
1111111111111110.567=>1,111,111,111,111,110.60
11111111111111110.567=>11,111,111,111,111,110
111111111111111110.567=>111,111,111,111,111,104
1111111111111111110.567=>1,111,111,111,111,111,170

I don't understand why the behavior changes. How should I print 1111111111111111110.567 as 1,111,111,111,111,111,110.57?

回答1:

The problem is that you can't represent 1111111111111111110.567 exactly as a double in the first place. (You can't even represent your shortest value exactly, but the inaccuracy will increase significantly as you increase the magnitude.)

A double only has about 17 significant digits of useful data anyway - you're trying to get 22 digits.

Use BigDecimal if you want more precision - but be aware that this will change other things too. What kind of value are you trying to represent, anyway? Natural values (weights, distances etc) are appropriate for double; artificial values (particularly currency values) are appropriate for BigDecimal.



回答2:

I managed to get this (You have to use BigDecimal):

import java.math.BigDecimal;
import java.text.NumberFormat;

public class Sandbox {
    public static void main(String[] args) {
        BigDecimal x = new BigDecimal("1111111111111111110.567");
        DecimalFormat formatter = new DecimalFormat("###,###.00");
        System.out.println(formatter.format(x));
    }
}

OUTPUT:

1,111,111,111,111,111,110.57

Resource Links: DecimalFormat and BigDecimal

One more thing, you have to enter the BigDecimal number as a String or else it will cause problems.

BigDecimal x = new BigDecimal(1111111111111111110.567) will output the following.

1,111,111,111,111,111,168.00