为什么我使用Long.parseLong(字符串s,int基数)和这个长二进制数会冒犯Java?

为什么我使用Long.parseLong(字符串s,int基数)和这个长二进制数会冒犯Java?,java,Java,我有以下代码: 为什么Java认为这不是有效的long @Test public void testOffendingBinaryString() { String offendingString = "1000000000000000000010101000000000000000000000000000000000000000"; assertEquals(64, offendingString.length()); Long.parseLong(offendingString,

我有以下代码:

为什么Java认为这不是有效的
long

@Test
public void testOffendingBinaryString() {
  String offendingString = "1000000000000000000010101000000000000000000000000000000000000000";
  assertEquals(64, offendingString.length());
  Long.parseLong(offendingString, 2);
}

因为它超出了long的有效值的范围。字符串:

"-111111111111111111101011000000000000000000000000000000000000000"
应该很好用。不能直接在中指定负数。如果您试图指定一个正数,那么这个数字太大,无法放入Java long中,Java long是一个用2s补码表示的有符号64位值(这意味着它基本上是63位+一个符号位(比这稍微复杂一点,请阅读2s补码页))。

Java long类型:

8字节有符号(2的补码)。 范围为-9223372036854775808 至+9223372036854775807


字符串的大小太长,请检查此项。数字在内部使用表示。这意味着数字只有63位,一位表示正数或负数。由于
Long.parseLong()
不适合解析2的补码中的数字,因此您的字符串是一个64位的正数,它超过了
Long

的最大正值
Long
存储在2的补码中,但解析方法需要直接二进制。因此,
字符串中的最大位数可以是63

@Test
public void testOffendingBinaryString() {
  String offendingString = "1000000000000000000010101000000000000000000000000000000000000000";
  assertEquals(64, offendingString.length());
  Long.parseLong(offendingString, 2);
}

使用常规二进制时,没有符号位。你可以传递一个长度为63的
字符串,然后在它前面加一个
-
如果你想要一个负
长的

这是Java中的一个bug,请看,他们在1.8中修复了它
-

Java是如何被冒犯的?出现任何异常?Java没有感觉;-)@Joachim Sauer没有感觉?那为什么Java会摇摆不定呢?Java不会。Swing没有尾随s;-)@Joachim Sauer只是为了让语法更恰当。但Java仍然有“面”,它是弹簧式的,它是摆动式的。二的补码与“符号的一位数”不同,因为如果是,则会有一个正零和一个负零。我没有说它是符号位,只是说它用于区分正数和负数。在我看来,没有必要在答案中解释这两个补语是如何起作用的。
@Test
public void testOffendingBinaryString() {
  String offendingString = "1000000000000000000010101000000000000000000000000000000000000000";
  assertEquals(64, offendingString.length());
  Long.parseLong(offendingString, 2);
}