1

I need format numbers like this:

23.0 -> 23
23.20 -> 23.20
23.00 -> 23
23.11 -> 23.11
23.2 -> 23.20
23.999 -> 24
23.001 -> 23
1345.999 -> 1346 // Edited the question to add this from the OP's comment

Here is my code: java:

  public static String toPrice(double number) {
         DecimalFormatSymbols formatSymbols = new DecimalFormatSymbols();
            formatSymbols.setGroupingSeparator(' ');
            DecimalFormat format = new DecimalFormat("#,###,###.##", formatSymbols);
            return format.format(number);
    
         }

kotlin:

fun Double.toPrice(): String =   DecimalFormat("#,###,###.##", DecimalFormatSymbols().apply {
                groupingSeparator = ' '
            }).format(this)

But for input 23.20 or 23.2 I get the result 23.2. This is wrong for me. I need 23.20. Which string pattern should I use to achieve this result? Please, help me.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
testovtest
  • 141
  • 1
  • 8
  • You are using the term "pattern" incorrectly. In programming, design patterns are very specific examples of solutions to specific problems. You just need a bit of help with formatting, though I think you're wrong. Displaying a number as 21.00 is saying that you know the number to a higher precision than a number you display as just 21. – NomadMaker Nov 02 '20 at 10:52
  • 2
    @NomadMaker The `DecimalFormat` class refers to its string template as a ‘pattern’ throughout; the constructor parameter in this case is called `pattern`.  So it seems perfectly reasonably to call it that.  (Design patterns aren't the only sort of pattern.) – gidds Nov 02 '20 at 12:38
  • @ArvindKumarAvinash What you said is not correct. The (my) answer on the linked question produces `23.20` for an input of `23.20`, and satisfies all the other examples too. It's very similar to Cenfracee's answer here. This question is a duplicate except for specifically mentioning `DecimalFormat`. I think `DecimalFormat` is not the right tool or the job here, `String.format()` is much simpler. – Adam Millerchip Nov 02 '20 at 13:06
  • Oh, the question was re-opened. Here's the duplicate: [Print float with two decimals unless number is a mathematical integer](https://stackoverflow.com/questions/64102602/print-float-with-two-decimals-unless-number-is-a-mathematical-integer). – Adam Millerchip Nov 02 '20 at 13:07
  • @ArvindKumarAvinash It's difficult to reply when you delete your comments. In the case of `23.001`, the answer on the above post will produce `23`, which is what was required. – Adam Millerchip Nov 02 '20 at 13:08
  • @AdamMillerchip - I had reopened it based on my initial analysis. On further analysis, I found that you are right. I've closed it again. Thank you. – Arvind Kumar Avinash Nov 02 '20 at 13:10

2 Answers2

5
public static String toPrice(double number) {
    if (number == (int) number) {
        return Integer.toString((int) number);
    } else {
        return String.format("%.2f", number);
    }
}

EDIT
To include thousand separator

public static String toPrice(double number) {
    if (number == (int) number) {
        return String.format("%,d",(int)number);
    } else {
        return String.format("%,.2f", number);
    }
}
3

Update

In case you need to format 1345.999 as 1346 (as mentioned in your comment), you can do so by adding a couple of extra steps in the original answer:

  1. Format the number with the pattern, #,###,###.00 and then remove all commas so that it can be parsed back to double.
  2. Parse the converted string into double and follow the rest of the solution as mentioned in the original answer.

Demo:

import java.text.DecimalFormat;
import java.text.NumberFormat;

public class Main {
    public static void main(String[] args) {
        System.out.println(getFromattedNumber(1234567.0));
        System.out.println(getFromattedNumber(1234567.20));
        System.out.println(getFromattedNumber(1234567.01));
        System.out.println(getFromattedNumber(1234567.00));
        System.out.println(getFromattedNumber(1345.999));
    }

    static String getFromattedNumber(double number) {
        NumberFormat format = new DecimalFormat("#,###,###.00");
        double num = Double.parseDouble(format.format(number).replace(",", ""));

        // Format for integer decimal numbers
        NumberFormat formatInt = new DecimalFormat("#,###,###");

        if ((int) num == num) {
            return formatInt.format(number);
        } else {
            return format.format(number);
        }
    }
}

Output:

1,234,567
1,234,567.20
1,234,567.01
1,234,567
1,346

Original answer

You will need to use two formats as shown below:

import java.text.DecimalFormat;
import java.text.NumberFormat;

public class Main {
    public static void main(String[] args) {
        System.out.println(getFromattedNumber(1234567.0));
        System.out.println(getFromattedNumber(1234567.20));
        System.out.println(getFromattedNumber(1234567.01));
        System.out.println(getFromattedNumber(1234567.00));
    }

    static String getFromattedNumber(double number) {
        // Format for integer decimal numbers
        NumberFormat format1 = new DecimalFormat("#,###,###");

        // Format for non-integer decimal numbers
        NumberFormat format2 = new DecimalFormat("#,###,###.00");

        if ((int) number == number) {
            return format1.format(number);
        } else {
            return format2.format(number);
        }
    }
}

Output:

1,234,567
1,234,567.20
1,234,567.01
1,234,567
Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
  • DecimalFormat by default uses RoundingMode.HALF_EVEN (as I need) And for example when my value is 1345.999 I get result 1 346.00 (two zeroes at the end, incorrect) – testovtest Nov 02 '20 at 11:48
  • @testovtest - `1346.00` is the correct result by using `RoundingMode.HALF_EVEN`. Check [this](https://stackoverflow.com/a/28134961/10819573) for an explanation. In case you need `1345.999` to be formatted as `1345.99`, use `RoundingMode.FLOOR`. – Arvind Kumar Avinash Nov 02 '20 at 12:07
  • For input 1345.999 I need output 1346 (rounded but without zeroes at the end) – testovtest Nov 02 '20 at 12:12
  • @testovtest - I've posted an update to fulfil this requirement. Feel free to comment in case of any doubt/issue. – Arvind Kumar Avinash Nov 02 '20 at 12:41