Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert String to Number, Java

Edit: Clarification convert any valid number encoding from a string to a number

How does one convert a string to a number, say just for integers, for all accepted integer formats, particularly the ones that throw NumberFormatException under Integer.parseInt. For example, the code

...
int i = 0xff;
System.out.println(i);
String s = "0xff";
System.out.println( Integer.parseInt(s) );
....

Will throw a NumberFormatException on the fourth line, even though the string is clearly a valid encoding for a hexadecimal integer. We can assume that we already know that the encoding is a valid number, say by checking it against a regex. It would be nice to also check for overflow (like Integer.parseInt does), but it would be okay if that has to be done as a separate step.

I could loop through every digit and manually calculate the composite, but that would pretty difficult. Is there a better way?

EDIT: a lot of people are answering this for hexidecimal, which is great, but not completely what I was asking (it's my fault, I used hexidecimal as the example). I'm wondering if there's a way to decode all valid java numbers. Long.decode is definitely great for just catching hex, but it fails on

222222L

which is a perfectly valid long. Do I have to catch for every different number format separately? I'm assuming you've used a regex to tell what category of number it is, i.e, distinguish floats, integers, etc.

like image 526
en_Knight Avatar asked Apr 30 '14 20:04

en_Knight


2 Answers

You could do

System.out.println(Integer.decode(s));
like image 153
Reimeus Avatar answered Sep 23 '22 07:09

Reimeus


You need to specify the base of the number you are trying to parse:

Integer.parseInt(s,16);

This will fail if you have that "0x" starting it off so you could just add a check:

if (s.startsWith("0x")) {
    s = s.substring(2);
}
Integer.parseInt(s,16);

EDIT

In response to the information that this was not a hex specific question I would recommend writing your own method to parse out all the numbers formats you like and build in on top of Integer.decode which can save you from having to handle a couple of cases.

I would say use regex or create your own methods to validate other formats:

public static int manualDecode(String s) throws NumberFormatException {

    // Match against #####L long format
    Pattern p = Pattern.compile("\\d+L");  // Matches ########L
    Matcher m = p.matcher(s);
    if (m.matches()) {
        return Integer.decode(s.substring(0,s.length()-1));
    }

    // Match against that weird underscore format
    p = Pattern.compile("(\\d{1,3})_((\\d{3})_)*?(\\d{3})"); // Matches ###_###_###_###_###
    m = p.matcher(s);
    if (m.matches()) {
        String reformattedString = "";
        char c;
        for (int i = 0; i < s.length(); i++) {
            c = s.charAt(i);
            if ( c >= '0' && c <= '9') {
                reformattedString += c;
            }
        }
        return Integer.decode(reformattedString);
    }
    // Add as many more as you wish
    throw new NumberFormatException();
}

public int parseIntExtended(String s) {
    try {
        return Integer.decode(s);
    } catch (NumberFormatException e) {
        return manualDecode(s);
    }
}
like image 27
Farmer Joe Avatar answered Sep 20 '22 07:09

Farmer Joe