Safe String to Bigdecimal Conversion

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 doubles 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 Strings into Numbers and Numbers into Strings 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
  • String#format(String, Object...)
    • This uses its own pattern rules as specified in the Javadoc of Formatter
  • PrintStream#printf(String, Object...)
    • This uses the same rules as 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.

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 BigDecimals 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



Leave a reply



Submit