You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 10:26:02