1

Java wonderfully provides Long.decode to parse most int formats, but not binary:

Long.decode("11") => 11
Long.decode("011") => 9
Long.decode("0x11") => 17
Long.decode("0b11") => java.lang.NumberFormatException

Is there a method that will parse a string containing a binary literal for me?

P.S. I understand if I wanted to extract the radix/value myself I could use the binary form of Long.parseLong, but ideally what I'm looking for would be a function that could parse "0b11" without any pre-processing.

5
  • 3
    Technically that's a String not a binary literal. With a binary literal you would just write: Long n = 0b11L; Commented Mar 3, 2017 at 4:18
  • Good point, will update title. Commented Mar 3, 2017 at 4:19
  • 2
    This has been my pet-peeve. It also does not have a method to parse integer strings with underscores (e.g. "100_000"), although it definitely accepts literals with underscores. Commented Mar 3, 2017 at 4:21
  • Does that mean that to your knowledge no good solution exists? Commented Mar 3, 2017 at 4:21
  • Honestly, "No" is fine provided someone has evidence that it doesn't exist in core Java or the standard library. Alternatively a good community library would suffice. Commented Mar 3, 2017 at 4:23

2 Answers 2

2

There is no way in the standard Java API. However, I would take a look at Long.decode() code and adapt it:

public static Long decode(String nm) throws NumberFormatException {
    int radix = 10;
    int index = 0;
    boolean negative = false;
    Long result;

    if (nm.length() == 0)
        throw new NumberFormatException("Zero length string");
    char firstChar = nm.charAt(0);
    // Handle sign, if present
    if (firstChar == '-') {
        negative = true;
        index++;
    } else if (firstChar == '+')
        index++;

    // Handle radix specifier, if present
    if (nm.startsWith("0x", index) || nm.startsWith("0X", index)) {
        index += 2;
        radix = 16;
    }
/// >>>> Add from here
    else if (nm.startsWith("0b", index) || nm.startsWith("0B", index)) {
        index += 2;
        radix = 2;
    }
/// <<<< to here
    else if (nm.startsWith("#", index)) {
        index ++;
        radix = 16;
    }
    else if (nm.startsWith("0", index) && nm.length() > 1 + index) {
        index ++;
        radix = 8;
    }

    if (nm.startsWith("-", index) || nm.startsWith("+", index))
        throw new NumberFormatException("Sign character in wrong position");

    try {
        result = Long.valueOf(nm.substring(index), radix);
        result = negative ? Long.valueOf(-result.longValue()) : result;
    } catch (NumberFormatException e) {
        // If number is Long.MIN_VALUE, we'll end up here. The next line
        // handles this case, and causes any genuine format error to be
        // rethrown.
        String constant = negative ? ("-" + nm.substring(index))
                                   : nm.substring(index);
        result = Long.valueOf(constant, radix);
    }
    return result;
}

That's as close as it can be to the original method (Ctrl+clicking core Java methods is a good experience).

Sign up to request clarification or add additional context in comments.

Comments

0

Java doesn't seem to provide one; however, is this code really that cumbersome that you need a library:

public static Long parseBinaryLiteral (String s)
{
    if (s == null)
        throw new NumberFormatException("null");

    // no need to check 0B
    s = s.toLowerCase();

    String p = "";

    if (s.startsWith("0b"))
        p = s.substring(2);
    else if (s.startsWith("-0b"))
        p = "-" + s.substring(3);
    else if (s.startsWith("+0b"))
        p = s.substring(3);
    else
        throw new NumberFormatException("For input string: \"" + s + "\"");

    return Long.parseLong(p, 2);
}

9 Comments

Cumbersome, no. But it's hard to write a correct implementation for this kind of stuff. For example your implementation has at least two bugs that I can spot without having read the spec. And I'd rather not read the spec.
What are the 2 bugs you see? I'm curious.
That's not a bug - it's just not supported yet :)
Haha, sure. But it's not trivial to make sure one's implementation is correct. I'm in the process of doing what you suggest now, but it's unfortunate that I'm putting in this effort and will likely still have "missing features" without realizing.
Good point. It's unfortunate that java doesn't support this - I'm a bit surprised. Hard to speculate as to why they didn't include it.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.