java parseLong对二进制字符串抛出NumberFormatException

nafvub8i  于 2023-02-15  发布在  Java
关注(0)|答案(3)|浏览(166)

我们有字节string s = "1111000000000111000000000001000000000010010000000000000000000000"(该值等于-1150951111012646912),如果我们使用Long.parseLong(s, 2),我们得到"
java.lang.NumberFormatException:对于输入字符串:"110000000100000001000000000011100000000000100000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
我修正了这个问题与这种方式转换

new BigInteger(s, 2).longValue();

请解释一下,我不明白发生了什么?
此值的情况相同:s = 1100000001000000010000000100000000001110000000010000010000000000(等于-4593600976060873728)

new BigInteger(s, 2).longValue();
6yt4nkrj

6yt4nkrj1#

简单地说,Integer.parseIntLong.parseLong都不能解析二进制补码负数,除非用显式的'+''-'符号替换符号位。
这可能与解析十进制数一致,如下所示:

String max = "9223372036854775807";  // Long.MAX_VALUE         
String maxPlus1 = "9223372036854775808"; // Long.MAX_VALUE+1 
long m = Long.parseLong(max,10); //OK
long m1 =Long.parseLong(maxPlus1,10)); // throws exception

要解析long的二进制补码值或任何其他值,可以使用Long.parseUnsignedLong。以下三个方法调用都能正确解析值,并输出Long.MIN_VALUE,第四个是问题中的特定值。

System.out.println(Long.parseUnsignedLong("1000000000000000000000000000000000000000000000000000000000000000",2));
System.out.println(Long.parseUnsignedLong("8000000000000000",16));
System.out.println(Long.parseUnsignedLong("9223372036854775808",10));
System.out.println(Long.parseUnsignedLong("1111000000000111000000000001000000000010010000000000000000000000",2));

印刷品

-9223372036854775808
-9223372036854775808
-9223372036854775808
-1150951111012646912
qoefvg9y

qoefvg9y2#

你传入的是一个大小为64的二进制字符串,它大于long类型的有符号字节的大小。由于parseLong不接受无符号二进制表示,而是希望在数字前面加上一个-或(可选的)+来表示符号,所以它会抛出一个错误。你可以传入parseLong类型的最大字节长度是63。
与第一个示例等效的parseLong调用是Long.parseLong("-111111111000111111111110111111111101110000000000000000000000", 2),使用-符号和数字的二进制补码。

gstyhher

gstyhher3#

您试图将64位无符号(长)整数分析为64位有符号(长)整数。
Java的long不是无符号的。您只能存储最多63位的正数。long9,223,372,036,854,775,8072^(63)
最高有效位(最左边)是有符号位。

  • 如果是以1开头的64位字符串,则为负。
  • 如果小于64位,则为正,并且不显示前导0。

注:任何前导零都不会显示。

import java.math.BigInteger;

public class NumberUtils {

  static final String MIN_SIGNED_LONG_BINARY = Long.toBinaryString(Long.MIN_VALUE);
  static final String MAX_SIGNED_LONG_BINARY =
      padStart(Long.toBinaryString(Long.MAX_VALUE), 64, "0");

  public static void main(String[] args) {
    parseBinary("1111000000000111000000000001000000000010010000000000000000000000");
    parseBinary("1100000001000000010000000100000000001110000000010000010000000000");
  }

  private static void parseBinary(String str) {
    BigInteger bigInt = new BigInteger(str, 2);
    System.out.println(bigInt.longValue());
    try {
      Long.parseLong(str, 2);
    } catch (NumberFormatException e) {
      System.out.printf(
          "Error:%n* Min: %s (%d bits)%n* Val: %s (%d bits)%n* Max: %s (%d bits)%n",
          MIN_SIGNED_LONG_BINARY,
          MIN_SIGNED_LONG_BINARY.length(),
          str,
          str.length(),
          MAX_SIGNED_LONG_BINARY,
          MAX_SIGNED_LONG_BINARY.length());
    }
  }

  public static String padStart(String inputString, int targetLength, String padString) {
    if (inputString.length() >= targetLength) return inputString;
    StringBuilder sb = new StringBuilder();
    while (sb.length() < targetLength - inputString.length()) {
      sb.append(padString);
    }
    return sb.append(inputString).toString();
  }
}

输出

-1150951111012646912
Error:
* Min: 1000000000000000000000000000000000000000000000000000000000000000 (64 bits)
* Val: 1111000000000111000000000001000000000010010000000000000000000000 (64 bits)
* Max: 0111111111111111111111111111111111111111111111111111111111111111 (64 bits)
-4593600976060873728
Error:
* Min: 1000000000000000000000000000000000000000000000000000000000000000 (64 bits)
* Val: 1100000001000000010000000100000000001110000000010000010000000000 (64 bits)
* Max: 0111111111111111111111111111111111111111111111111111111111111111 (64 bits)

相关问题