I'm trying to convert a string to a BigDecimal but I can't manage to preserve the format. the String is a price/number with a format which can either be #,###.00 or # ###,00
this is what i've tried but it doesn't keep the format intact. 37,717,840.33 ==> 37717840.33
public static BigDecimal convertStringtoDecimal(String patternDecimalFormat,
String pattern, String price) {
DecimalFormatSymbols symbols = new DecimalFormatSymbols();
symbols.setDecimalSeparator(pattern.charAt(0));
symbols.setGroupingSeparator(pattern.charAt(1));
DecimalFormat decimalFormat = new DecimalFormat(patternDecimalFormat, symbols);
decimalFormat.setParseBigDecimal(true);
BigDecimal bigDecimal = null;
try {
bigDecimal = (BigDecimal) decimalFormat.parse(price);
} catch (ParseException e) {
LOGGER.warn("Exception convertion string to dec", e);
}
return bigDecimal ;
}
A BigDecimal
is an "[i]mmutable, arbitrary-precision signed decimal number[]".
What is "arbitrary-precision"? This Wikipedia article has this to say in its introduction:
In computer science, arbitrary-precision arithmetic, also called bignum arithmetic, multiple-precision arithmetic, or sometimes infinite-precision arithmetic, indicates that calculations are performed on numbers whose digits of precision are limited only by the available memory of the host system. This contrasts with the faster fixed-precision arithmetic found in most arithmetic logic unit (ALU) hardware, which typically offers between 8 and 64 bits of precision.
In other words, BigDecimal
is a special type of Number
that allows "perfect" (it can't handle irrational numbers) precision. This is in contrast to Double
(or the primitive type, double
) which has "fixed-precision" and therefore can't represent all the numbers that BigDecimal
can. This increase in precision comes at the cost of increased memory use and much slower mathematical operations (computers can handle double
s and such at a hardware level).
Why am I bringing all this up? Because I want to point out that a BigDecimal
is nothing more than a fancy number. And numbers, at least in Java, have no concept of formatting. With that in mind you realize it makes no sense to expect a BigDecimal
to maintain the format of the String
used to create it. There are hints at this in your own code; you had to use the intermediary DecimalFormat
object to parse your String
into a BigDecimal
. Why would you have to do this when BigDecimal
has a constructor that takes a String
? It's because the BigDecimal
constructor is very limited. If you were to try to convert your String
using the constructor you'd get a NumberFormatExcepton
with the following message: "Character , is neither a decimal digit number, decimal point, nor "e" notation exponential mark."
As you can see, it is the DecimalFormat
that understands the String
in your code. The reason for this is because that's what DecimalFormat
is designed for. The class exists so you can parse String
s into Number
s and Number
s into String
s using a specified pattern (which is normally based on the user's Locale
). When you want to display a Number
such as a BigDecimal
but in a formatted fashion you have to use a class such as DecimalFormat
. Some options to convert a number into a String
would be:
DecimalFormat
NumberFormat
String#format(String, Object...)
Formatter
PrintStream#printf(String, Object...)
String#format(String, Object...)
.System.out
is a PrintStream
As I pointed out in the question comments, in your case you should be able to get back the formatted String
by calling
String formattedString = decimalFormat.format(bigDecimal);
on the same DecimalFormat
or at least one that was configured the same.