public static String currencyFormat(BigDecimal n) {
return NumberFormat.getCurrencyInstance().format(n);
}
It will use your JVM’s current default Locale to choose your currency symbol. Or you can specify a Locale.
NumberFormat.getInstance(Locale.US)
For more info, see NumberFormat class.
public static String currencyFormat(BigDecimal n) {
return NumberFormat.getCurrencyInstance().format(n);
}
It will use your JVM’s current default Locale to choose your currency symbol. Or you can specify a Locale.
NumberFormat.getInstance(Locale.US)
For more info, see NumberFormat class.
To set thousand separator, say 123,456.78 you have to use DecimalFormat:
DecimalFormat df = new DecimalFormat("#,###.00");
System.out.println(df.format(new BigDecimal(123456.75)));
System.out.println(df.format(new BigDecimal(123456.00)));
System.out.println(df.format(new BigDecimal(123456123456.78)));
Here is the result:
123,456.75
123,456.00
123,456,123,456.78
Although I set #,###.00 mask, it successfully formats the longer values too.
Note that the comma(,) separator in result depends on your locale. It may be just space( ) for Russian locale.
Here are a few hints:
- Use
BigDecimalfor computations if you need the precision that it offers (Money values often need this). - Use the
NumberFormatclass for display. This class will take care of localization issues for amounts in different currencies. However, it will take in only primitives; therefore, if you can accept the small change in accuracy due to transformation to adouble, you could use this class. - When using the
NumberFormatclass, use thescale()method on theBigDecimalinstance to set the precision and the rounding method.
PS: In case you were wondering, BigDecimal is always better than double, when you have to represent money values in Java.
PPS:
Creating BigDecimal instances
This is fairly simple since BigDecimal provides constructors to take in primitive values, and String objects. You could use those, preferably the one taking the String object. For example,
BigDecimal modelVal = new BigDecimal("24.455");
BigDecimal displayVal = modelVal.setScale(2, RoundingMode.HALF_EVEN);
Displaying BigDecimal instances
You could use the setMinimumFractionDigits and setMaximumFractionDigits method calls to restrict the amount of data being displayed.
NumberFormat usdCostFormat = NumberFormat.getCurrencyInstance(Locale.US);
usdCostFormat.setMinimumFractionDigits( 1 );
usdCostFormat.setMaximumFractionDigits( 2 );
System.out.println( usdCostFormat.format(displayVal.doubleValue()) );
I would recommend a little research on Money Pattern. Martin Fowler in his book Analysis pattern has covered this in more detail.
public class Money {
private static final Currency USD = Currency.getInstance("USD");
private static final RoundingMode DEFAULT_ROUNDING = RoundingMode.HALF_EVEN;
private final BigDecimal amount;
private final Currency currency;
public static Money dollars(BigDecimal amount) {
return new Money(amount, USD);
}
Money(BigDecimal amount, Currency currency) {
this(amount, currency, DEFAULT_ROUNDING);
}
Money(BigDecimal amount, Currency currency, RoundingMode rounding) {
this.currency = currency;
this.amount = amount.setScale(currency.getDefaultFractionDigits(), rounding);
}
public BigDecimal getAmount() {
return amount;
}
public Currency getCurrency() {
return currency;
}
@Override
public String toString() {
return getCurrency().getSymbol() + " " + getAmount();
}
public String toString(Locale locale) {
return getCurrency().getSymbol(locale) + " " + getAmount();
}
}
Coming to the usage:
You would represent all monies using Money object as opposed to BigDecimal. Representing money as big decimal will mean that you will have the to format the money every where you display it. Just imagine if the display standard changes. You will have to make the edits all over the place. Instead using the Money pattern you centralize the formatting of money to a single location.
Money price = Money.dollars(38.28);
System.out.println(price);
It all comes down to precision, and Java's BigDecimal seems the correct answer on that platform because it gives you the best support for specifying and preserving what can be highly variable precision.
A millionth of a cent is only 10-5 from a shift in payable amount, and it's not that hard to come up with a situation where that level of precision matters.
- Company A is publicly traded, with fifty million (5x106) shares outstanding and a current price of $10.
- Person B buys $1 of Company A, through a broker. They now own one-tenth of a share, or a one five-hundred-millionth of Company A. (10-7).
- Company A is found to be absurdly over-valued, and after a bit of a scandal winds up accepting a stock-swap purchase by Company C at a value of $1,000 (103), with each shareholder getting the equivalent number to be paid out equally to the shareholders in either cash or stock.
- How much cash or stock can Person B get? Note that if you get the number wrong, Person B (who happens to be an out-of-work lawyer in his 30s) can mess up the entire deal and possibly earn himself a paycheck by suing for his value lost plus legal fees.
Now, the valuation is fairly absurd on purpose, but the same "you need to get it right or it explodes" details even if the numbers are only off by a minuscule amount.
The right type to represent currency values depends of the application.
Two plausible choices are a type capable of exact arithmetic or a floating point type. Please remember two facts:
In floating point arithmetic, usual algebraic identities (like commutativity and associativity) does not hold any more. They still hold in exact arithmetic.
In exact arithmetic, it is not possible to work with functions other than polynomials, so we cannot use the square root or the exponential functions. Floating point arithmetics allows to use them.
In a double accounting personal finance software, exact arithmetic is preferrable. We expect all of the cashflows recorded to sum up to zero. Since this is an algebraic identity, we can only verify it if we use exact arithmetics. Here using a floating point would make the whole principe of double accounting useless.
In an internal software used by a clearing house, exact arithmetic is also mandatory, basically for the same reason as previously. There is a conservation principle, so that cashflows should always sum up to zero. Since the program has to satisfy an invariant of an algebraic nature, it must rely on exact arithmetics.
In a pricing or risk management software implementing methods of mathematical finance, complex computations reminescent of physics simulations are performed and expectations estimates are computed. The very nature of this problem require the use of floating point numbers.