Country Currency formatting using 'NumberFormat' class Java

338 views Asked by At

I'm currently working on a task that involves taking a double-precision number representing a sum of money and using the NumberFormat class' getCurrencyInstance method to convert it into the currency formats of US, India, China, and France.

Input:

A single double-precision number denoting 'payment'

Output:

On the first line, print US: 'u' where 'u' is 'payment' formatted for US currency.
On the second line, print India: 'i' where 'i' is 'payment' formatted for the Indian currency.
On the third line, print China: 'c' where 'c' is 'payment' formatted for Chinese currency.
On the fourth line, print France: 'f' where 'f' is formatted for French currency.

Sample input:

12324.134

Sample output:

US: $12,324.13

India: Rs.12,324.13

China: ¥12,324.13

France: 12 324,13 €

My code:

import java.util.*;
import java.text.*;
import java.util.Currency;

public class Solution {
    
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        double payment = scanner.nextDouble();
        scanner.close();
        
        Locale indiaLocale = new Locale("en", "IN");
        
        Locale locale = Locale.US;
        Currency us = Currency.getInstance(locale);
        String symbol = us.getSymbol(locale);
        System.out.println("US: " + symbol + payment);
        
        Locale locale2 = indiaLocale;
        Currency in = Currency.getInstance(locale2);
        String symbol2 = in.getSymbol(locale2);
        System.out.println("India: " + symbol2 + payment);
        
        Locale locale3 = Locale.CHINA;
        Currency ch = Currency.getInstance(locale3);
        String symbol3 = ch.getSymbol(locale3);
        System.out.println("China: " + symbol3 + payment);
        
        Locale locale4 = Locale.FRANCE;
        Currency fr = Currency.getInstance(locale4);
        String symbol4 = fr.getSymbol(locale4);
        System.out.println("France: " + payment + " " + symbol4);
    }
}

My input:

12324.134

My output:

US: $12324.134

India: Rs.12324.134

China: ¥12324.134

France: 12324.134 €

My problem lies in the format of the input, '12324.134'. As you can see, I've managed to output the right currency symbols, especially India as India does not have a built-in Locale, so I had to construct one where the language is en (i.e., English).

I just can't seem to get the commas in the right place and for some reason, France's expected output has a space after the first 2 digits. It might be because I haven't used the right methods of the Currency class but this is where Im stuck at. Any advice is appreciated.

2

There are 2 answers

2
Andrej Istomin On BEST ANSWER

NumberFormat.getCurrencyInstance

You probably should use NumberFormat.getCurrencyInstance and NumberFormat.format. Try this:

public static void main(String[] args) {
    double payment = 12324.134; // I'd use BigDecimal instead of double here, BTW. See the comment from another user under your post.

    Locale us = Locale.US;
    System.out.println("US: " + NumberFormat.getCurrencyInstance(us).format(payment));

    Locale india = new Locale("en", "IN");
    System.out.println("India: " + NumberFormat.getCurrencyInstance(india).format(payment));

    Locale china = Locale.CHINA;
    System.out.println("China: " + NumberFormat.getCurrencyInstance(china).format(payment));

    Locale france = Locale.FRANCE;
    System.out.println("France: " + NumberFormat.getCurrencyInstance(france).format(payment));
}

The output is:

US: $12,324.13
India: ₹12,324.13
China: ¥12,324.13
France: 12 324,13 €

It is even said in your task:

using the NumberFormat class' getCurrencyInstance method

0
Reilas On

"... I'm currently working on a task that involves taking a double-precision number representing a sum of money and using the NumberFormat class' getCurrencyInstance method to convert it into the currency formats of US, India, China, and France. ..."

In you're example you are using Currency#getInstance which is different than NumberFormat#getCurrencyInstance.

And, you should consider switching to the BigDecimal class, as recommended by Java.

Primitive Data Types (The Java™ Tutorials > Learning the Java Language > Language Basics).

"... float: ... This data type should never be used for precise values, such as currency. For that, you will need to use the java.math.BigDecimal class instead. Numbers and Strings covers BigDecimal and other useful classes provided by the Java platform. ..."

The recommendation is to use a "half-even" rounding-mode, as specified by the RoundingMode#HALF_EVEN JavaDoc.

"... API Note:
This is the rounding mode that statistically minimizes cumulative error when applied repeatedly over a sequence of calculations. It is sometimes known as "Banker's rounding," and is chiefly used in the USA. This rounding mode is analogous to the rounding policy used for most float and double arithmetic operators in Java (JLS 15.4). This mode corresponds to the IEEE 754 rounding-direction attribute roundTiesToEven. ..."

The Scanner class also conveniently provides a nextBigDecimal method.

BigDecimal payment = scanner.nextBigDecimal().setScale(2, HALF_EVEN);

Output

12324.134
US: $12324.13
India: ₹12324.13
China: ¥12324.13
France: 12324.13 €

"... My problem lies in the format of the input, '12324.134'. ...

... I just can't seem to get the commas in the right place and for some reason, France's expected output has a space after the first 2 digits. It might be because I haven't used the right methods of the Currency class but this is where Im stuck at. Any advice is appreciated."

Here is a relevant Java tutorial on "Customizing Formats".
Customizing Formats (The Java™ Tutorials > Internationalization > Formatting).

And, here is a re-factor.

Note that Currency.getInstance(Locale.CHINA).getSymbol() returns a different symbol than the format method, CN¥ over ¥.

Scanner scanner = new Scanner(System.in);
BigDecimal payment = scanner.nextBigDecimal().setScale(2, HALF_EVEN);
scanner.close();
DecimalFormat df;
for (Locale locale : List.of(US, new Locale("en", "IN"), CHINA, FRANCE)) {
    df = (DecimalFormat) NumberFormat.getCurrencyInstance(locale);
    System.out.printf("%s: %s%n", locale.toString(), df.format(payment));
}

Output

12324.134
en_US: $12,324.13
en_IN: ₹12,324.13
zh_CN: ¥12,324.13
fr_FR: 12 324,13 €