1

I am converting numbers like 5.326.236,56 (money), from a txt and first removing dots and commas, but im losing the decimals, and I already defined the columns as:

@Column(name = "total", precision = 16, scale = 2)
private BigDecimal total;

but I am losing the last 2 digits that correspond to Decimal part

Here is my code:

private BigDecimal parseBigLong(String stringNumber) {
    String cvalue = "";
    for (int n = 0; n < stringNumber.length(); n++) {
        char c = stringNumber.charAt(n);
        if (!(".").equals(String.valueOf(c))) {
            if (!(",").equals(String.valueOf(c))) {
                if (!("-").equals(String.valueOf(c))) {
                    cvalue = cvalue + c;
                }
            }
        }
    }
    BigDecimal bigDecimal = ( BigDecimal.valueOf(Long.parseLong(cvalue) / 100));

    return bigDecimal;
}
Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
Jeypi
  • 25
  • 7

2 Answers2

5

Basically, you are doing an integer division on the long before constructing the BigDecimal.

Naturally, the integer division is producing another long ... which cannot represent those two digits after the decimal point.

You can avoid this by doing the division using BigDecimal:

BigDecimal bigDecimal = BigDecimal.valueOf(Long.parseLong(cvalue))
        .divide(new BigDecimal(100));

Or if you don't need to enforce the constraint that cvalue is a valid integer (long) representation:

BigDecimal bigDecimal = (new BigDecimal(cvalue))
        .divide(new BigDecimal(100));

There may be a better way. The DecimalFormat class understands all sorts of (localized) number formats. If you create a suitable format and then call setParseBigDecimal(true) the format's parse method will produce a BigDecimal ... directly ... without any string bashing to get rid of comma and period characters. (And you won't need to assume that the input number has exactly two digits after the decimal.)

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
0

First, your conversion logic is strange:

You are ripping off all -, , and . from your String, and assume it to be 2 decimals when constructing the BigDecimal.

Which means, if you are given a string 1234.5678, you are going to build 123456.78 as the result.

Depending on what's your intention, here are the answers:

  1. If you want to convert to BigDecimal based on the value in input string

    Which means, if you want String "1,234.5678" to become 1234.5678 in BigDecimal, you could make use of DecimalFormat, as described in this question: https://stackoverflow.com/a/18231943/395202

  2. If the strange logic is what you intended to do

    Which means, if you want String "1,234.5678" to become 123456.78 in BigDecimal, the specific problem in your code is you are doing a long division, and use the result to construct BigDecimal.

    In Java (and many other language), division of integer with integer is going to give you integer as result, so 123456 / 100 is going to give you 1234.

    What you want to achieve could be done by

    BigDecimal result = BigDecimal.valueOf(longValue).divide(BigDecimal.valueOf(100));
    

    Going back to your code, there are a lot of other problems:

    1. Your string concatenation logic is highly inefficient. You could use StringBuilder (or other way I am suggesting soon)
    2. You do not need to convert a char to a String to do comparison. So you

      if (!(".").equals(String.valueOf(c))) {
      

      should be written

      if (c != '.') {
      
    3. You could simply use regex to cleanse your input string:

      String cvalue = stringNumber.replaceAll("[.,-]", "");
      
Adrian Shum
  • 38,812
  • 10
  • 83
  • 131
  • im always getting numbers with two decimals precicion, not three or more, inproving the code then, thanks you a lot. – Jeypi Oct 25 '18 at 13:13