为何Long.parseLong解析特定二进制字符串会抛出NumberFormatException?
为什么Long.parseLong解析二进制补码字符串会抛异常,而BigInteger转long却可以?
核心原因:两者的二进制字符串解析规则完全不同
1. Long.parseLong的限制
Long.parseLong(s, 2)的解析逻辑有明确约束:
- 只有当字符串以
'-'开头时,才会将后续内容当作无符号二进制正数解析,再取负数; - 若字符串不以
'-'开头,会直接当作无符号二进制正数处理,要求数值不能超过Long.MAX_VALUE(即2^63-1)。
你提供的二进制字符串是64位补码形式(最高位为1,表示负数),但没有负号前缀。此时parseLong会把它当成一个64位无符号正数,数值为2^63 + 后63位的数值,显然超出了Long.MAX_VALUE的范围,因此抛出NumberFormatException。
2. BigInteger的解析逻辑
new BigInteger(s, 2)是直接按照二进制补码规则解析字符串:
- 当字符串长度为64位且最高位为1时,会自动识别为负数,解析出对应的十进制数值;
- 只要该数值落在
long的合法范围(-2^63到2^63-1)内,调用longValue()就能正确转换为long类型值。
针对你的例子验证
以第一个二进制字符串为例:
- 64位长度且最高位为1,
Long.parseLong将其视为超大无符号正数,超出范围抛异常; BigInteger按补码解析出-1150951111012646912,该值在long范围内,因此longValue()能正确返回结果。
额外补充:用Long.parseLong处理补码字符串的替代方案
如果想直接用Long相关方法处理这类补码字符串,有两种可行方式:
- 手动计算:判断最高位为1后,取后63位转成long,再减去
2^63得到对应负数; - 使用
Long.parseUnsignedLong(s, 2)解析为无符号长整数,再强制转换为long(无符号64位值转有符号long,正好对应补码负数)。
内容的提问来源于stack exchange,提问作者za1ra1za1
相关产品推荐
相关产品推荐

