Safe String to BigDecimal conversion
Check out setParseBigDecimal
in DecimalFormat. With this setter, parse
will return a BigDecimal for you.
How can I parse a String to BigDecimal?
Try this
// Create a DecimalFormat that fits your requirements
DecimalFormatSymbols symbols = new DecimalFormatSymbols();
symbols.setGroupingSeparator(',');
symbols.setDecimalSeparator('.');
String pattern = "#,##0.0#";
DecimalFormat decimalFormat = new DecimalFormat(pattern, symbols);
decimalFormat.setParseBigDecimal(true);
// parse the string
BigDecimal bigDecimal = (BigDecimal) decimalFormat.parse("10,692,467,440,017.120");
System.out.println(bigDecimal);
If you are building an application with I18N support you should use DecimalFormatSymbols(Locale)
Also keep in mind that decimalFormat.parse
can throw a ParseException
so you need to handle it (with try/catch) or throw it and let another part of your program handle it
Convert String to BigDecimal without losing format
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
- Or more generally, its superclass
NumberFormat
- Or more generally, its superclass
String#format(String, Object...)
- This uses its own pattern rules as specified in the Javadoc of
Formatter
- This uses its own pattern rules as specified in the Javadoc of
PrintStream#printf(String, Object...)
- This uses the same rules as
String#format(String, Object...)
. System.out
is aPrintStream
- This uses the same rules as
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.
ConvertString to Big Decimal in JAVA
The problem here is that your String contains alphabetic characters so it won't be possible to convert it to BigDecimal
, that's why you got NumberFormatException
.
You need to replace these alphabetic characters before trying to convert it:
String a = transaction.getBeneAmt();
log.info(a);
tran.setTransAmt(new BigDecimal(a.replaceAll("[a-zA-Z,]", "").trim()));
tranRepository.saveAndFlush(trangloTran);
Converting String to BigDecimal with leading zeros
You seem to indicate in comments that the initial string, "0087"
, is a fixed-point representation with two decimal places, there therefore being an implicit decimal point before the last two digits. There are several ways that you could convert that to a corresponding BigDecimal
, but myself, I would go with this:
BigDecimal result = BigDecimal.valueOf(Long.parseLong("0087"), 2);
The key here is to understand that BigDecimal
s have two characteristic properties: an arbitrary-length sequence of decimal digits, and a scale conveying the place value of the least-significant digit, in the form of the number of digits to the right of the decimal point. The particular factory method demonstrated above accepts those as separate arguments, though it only works if the digit string is short enough to be represented as a long
. The 2
corresponds directly to the number of (implicitly) fractional digits in your input.
Outputting the resulting BigDecimal
as "00.87" instead of "0.87" is a separate issue, but doable, if it's really something you want.
Related Topics
How to Access Resources in Jar File
What's the Difference Between Spring Data's Mongotemplate and Mongorepository
Storing a Map<String,String> Using JPA
Static Fields on a Null Reference in Java
Assert Equals Between 2 Lists in Junit
Take N Random Elements from a List<E>
Varying Behavior for Possible Loss of Precision
Creating Java Date Object from Year,Month,Day
Spring Boot Rest API - Request Timeout
No-Throw Virtualmachineerror Guarantees
In Java, When Should I Create a Checked Exception, and When Should It Be a Runtime Exception
Why Is Class.Newinstance() "Evil"
Get the Index of a Pattern in a String Using Regex
Java Regex Replace with Capturing Group