为啥 Integer.MIN_VALUE 的负数给出相同的值? [复制]

Posted

技术标签:

【中文标题】为啥 Integer.MIN_VALUE 的负数给出相同的值? [复制]【英文标题】:Why does the negative of Integer.MIN_VALUE give the same value? [duplicate]为什么 Integer.MIN_VALUE 的负数给出相同的值? [复制] 【发布时间】:2015-10-10 23:42:35 【问题描述】:

考虑下面的 java 代码。

Integer value = Integer.MIN_VALUE;
System.out.println(value);

value = -value;
System.out.println(value);

输出

-2147483648
-2147483648

Integer.MIN_VALUE 值的负值如何产生相同的值? 但是结果不能是2147483648,因为Java中Integer的最大值是2147483647

但是想知道为什么-2147483648?内部发生了什么样的按位运算?

【问题讨论】:

对于重新开放的选民,重复中的this 答案解释了Integer.MIN_VALUE 的否定。重复不是关于相同的问题,而是关于这个问题在这里已经有答案,正如标签所述。 【参考方案1】:

内部发生了什么样的按位运算?

Java 使用two's complement 表示带符号的数字。因此,改变符号的操作,包括两个步骤:

    反转原始值的位,并且 将1 添加到结果中。

2147483648的表示如下:

10000000000000000000000000000000

反转它产生

01111111111111111111111111111111

添加1 使其再次成为相同的数字,即

10000000000000000000000000000000

由于整数溢出。

【讨论】:

你为什么把它限制为正数作为输入? @laune 我明白你的意思。编辑以避免混淆。 @Codebender 1 相加的结果大于int 可以容纳的最大正值,所以这是溢出。 另一个要点:从技术上讲,将 1 加到 011...1 不会导致 n 位加法器溢出,即在这种情况下不会设置进位标志。只有将第一位解释为符号位才会产生“环绕”效果。 @laune 在overflow, or "V", flag 将被设置为结果的意义上,这是一个溢出。【参考方案2】:

当您否定-2147483648 时,它解析为2147483648,它超过了Integer.MAX_VALUE1。然后值再次溢出到Integer.MIN_VALUE

来自JLS:

整数类型有 byte、short、int 和 long,其值为 8 位、16 位、32 位和 64 位有符号二进制补码整数。

因此,对整数执行的每个一元运算实际上都将应用于数字的二进制补码表示。 当到达Integer.MAX_VALUE 时,它将由一个前导0 和31 个1 位组成。添加1 将使其成为一个前导1 和31 尾随0s 的数字,这实际上是Integer.MIN_VALUE 的二进制补码表示。

【讨论】:

When the Integer.MAX_VALUE is reached it will consist of 32 1 bits. Adding 1 would make it 33-bit number with a leading 1 and trailing 0s. - 你搞错了。 Integer.MAX_VALUE 是一个 0,后跟 31 个 1 位。加一得到 1 后跟 31 个 0 位,这是 Integer.MIN_VALUE 的二进制补码表示

以上是关于为啥 Integer.MIN_VALUE 的负数给出相同的值? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

Kafka的分区选择算法

Integer.MAX_VALUE 和 Integer.MIN_VALUE

Integer.MIN_VALUE和Integer.MAX_VALUE

Integer.MIN_VALUE

从十六进制解析 Integer.MIN_VALUE 会导致 NumberFormatException

Integer.MAX_VALUE和Integer.MIN_VALUE的解释,用于查找数组中的最小值和最大值