【问题标题】:Java parse int/long from binary literal stringJava 从二进制文字字符串中解析 int/long
【发布时间】:2017-03-03 04:09:08
【问题描述】:

Java 出色地提供了Long.decode 来解析大多数 int 格式,但不是二进制:

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

有没有一种方法可以为我解析包含二进制文字的字符串?

附: 我知道如果我想自己提取基数/值,我可以使用Long.parseLong 的二进制形式,但理想情况下,我正在寻找一个无需任何预处理即可解析"0b11" 的函数。

【问题讨论】:

  • 从技术上讲,这是一个字符串而不是二进制文字。使用二进制文字,您只需编写:Long n = 0b11L;
  • 好点,将更新标题。
  • 这一直是我的烦恼。它也没有用underscores(例如“100_000”)解析整数字符串的方法,尽管它肯定接受带有下划线的literals
  • 这是否意味着据您所知不存在好的解决方案?
  • 老实说,“不”很好,只要有人有证据证明它在核心 Java 或标准库中不存在。或者,一个好的社区图书馆就足够了。

标签: java literals


【解决方案1】:

标准的 Java API 没有办法。不过,我会看一下Long.decode() 代码并对其进行调整:

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;
}

这与原始方法尽可能接近(Ctrl+单击核心 Java 方法是一种很好的体验)。

【讨论】:

    【解决方案2】:

    Java 似乎没有提供;但是,这段代码真的那么麻烦,需要一个库吗:

    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);
    }
    

    【讨论】:

    • 繁琐,没有。但是很难为这种东西编写一个正确的实现。例如,您的实现至少有两个我可以在没有阅读规范的情况下发现的错误。而且我宁愿不阅读规范。
    • 您看到的 2 个错误是什么?我很好奇。
    • 这不是错误 - 只是还不支持 :)
    • 哈哈,当然。但是确保一个人的实施是正确的并非易事。我现在正在按照您的建议进行操作,但不幸的是,我正在努力并且可能仍然会在没有意识到的情况下出现“缺失的功能”。
    • 好点。不幸的是java不支持这个 - 我有点惊讶。很难推测他们为什么不包含它。
    猜你喜欢
    • 1970-01-01
    • 2023-04-04
    • 2017-05-29
    • 2015-11-23
    • 2013-01-30
    • 1970-01-01
    • 2021-06-19
    • 2016-06-29
    • 1970-01-01
    相关资源
    最近更新 更多