-1

I have a method which tries to convert strings into long:

public static Long getLong(String str) {
        long multiplier = 1;
        try {
            Long value = -1L;
            str = str.replaceAll("\\s", ""); // remove whitespace
            str = str.replaceAll("%", "");
            str = str.replaceAll(",", "");
            if (str.contains("M")) {
                str = str.replaceAll("M", "");
                multiplier = 1000000;
            } else if (str.contains("B")) {
                str = str.replaceAll("B", "");
                multiplier = 1000000000;
            } else if (str.contains("K")){
                str =   str.replaceAll("K", "");
                multiplier  =   1000;
            }
            // an exception is thrown for values like 199.00, so removing
            // decimals if any
            str = str.contains(".") ? str.substring(0, str.lastIndexOf(".")) : str;
            value = Long.valueOf(str);
            value = value * multiplier;

            return value;
        } catch (Exception e) {
            throw new RuntimeException(str + " cannot be parsed into long value");
        }

This method works fine values like "1K", "300M", "2B", "0" but not for the values like 3.14M or 1.1K. As mentioned in above comment Long.valueOf(str) throws exception if it has to take a input like 1.24 so I have to remove the digits after decimal (which I don't want to)

3 Answers3

6

Use a java.math.BigDecimal instead of a Long. This will preserve the decimal portion.

Note: DO NOT use float or double. You may run into weird precision issues while parsing the string values.

metacubed
  • 7,031
  • 6
  • 36
  • 65
  • I agree, this is better solution – Leos Literak May 11 '14 at 09:54
  • You will not get "weird" precision issues for up to 15 digits of accuracy. The problem with using `double` is that developers don't understand it, not a problem with `double` itself. – Peter Lawrey May 11 '14 at 10:10
  • @PeterLawrey It is better to stick to data types which were designed for the scenario in question. `Float` and `Double` are not meant for representing _arbitrary_ decimal numbers, because of the inherent nature of floating-point formats. – metacubed May 11 '14 at 10:22
  • 1
    @metacubed I totally agree that `double` is not appropriate for arbitrary precision, however there is little in real life which conforms to arbitrary precision. – Peter Lawrey May 12 '14 at 09:37
0

Instead of

value = Long.valueOf(str);

use:

value = Float.valueOf(str); or value = Double.valueOf(str);

Obviously change the type of value to match which one you choose. The reason behind the is that long represents a long integer, and cannot contain numbers with decimal points.

Here's a link describing the primitive Java data types.

Jurgen Camilleri
  • 3,559
  • 20
  • 45
0
if (str.contains("M")) {
            str = str.replaceAll("M", "");
            multiplier = 1000000;

The multiplier here is a million.

        } else if (str.contains("B")) {
            str = str.replaceAll("B", "");
            multiplier = 1000000000;

So the multiplier here should be 1, not 1,000,000,000.

        } else if (str.contains("K")){
            str =   str.replaceAll("K", "");
            multiplier  =   1000;
        }

This multiplier is correct.

user207421
  • 305,947
  • 44
  • 307
  • 483