为什么Integer.MAX_VALUE + 1 == Integer.MIN_VALUE?

Ole*_*eev 26 java integer integer-overflow twos-complement jls

System.out.println(Integer.MAX_VALUE + 1 == Integer.MIN_VALUE);

是真的.

我知道Java中的整数是32位,不能超过2 ^ 31-1,但我不明白为什么在MAX_VALUE中加1会导致MIN_VALUE而不是某种异常.没有像Ruby那样透明地转换为更大的类型.

是否在某处指定了此行为?我可以依靠它吗?

Boz*_*zho 29

因为整数溢出.当它溢出时,下一个值是Integer.MIN_VALUE.相关的JLS

如果整数加法溢出,则结果是数学和的低阶位,如某些足够大的二进制补码格式所示.如果发生溢出,则结果的符号与两个操作数值的数学和的符号不同.


fal*_*lla 25

整数存储溢出,并且没有以任何方式指示,如JSL 3rd Ed中所述.:

内置整数运算符不以任何方式指示溢出或下溢.整数运算符可以抛出空引用的NullPointerExceptionif unboxing转换(第5.1.8节).除此之外,唯一可以抛出异常的整数运算符(第11 节)是整数除运算符/ (第15.17.2节)和整数余数运算符% (第15.17.3节),ArithmeticException如果右边的操作数是零,以及增量和减量运算符++(§15.15.1,§15.15.2)和--(§15.14.3,§15.14.2),它们可以抛出OutOfMemoryErrorif拳击转换(§5.1.7),并且没有足够的内存可用于执行转换.

4位存储中的示例:

MAX_INT: 0111 (7)
MIN_INT: 1000 (-8)
Run Code Online (Sandbox Code Playgroud)

MAX_INT + 1:

 0111+
 0001
 ----
 1000
Run Code Online (Sandbox Code Playgroud)


ARR*_*RRG 8

您必须了解整数值如何以二进制形式表示,以及二进制加法的工作原理.Java使用称为二进制补码的表示,其中数字的第一位表示其符号.每当你向最大的java Integer(其位符号为0)加1时,它的位符号变为1,数字变为负数.

此链接解释了更多详细信息:http://www.cs.grinnell.edu/~rebelsky/Espresso/Readings/binary.html#integers-in-java

-

Java语言规范在此处理此行为:http://docs.oracle.com/javase/specs/jls/se6/html/expressions.html#15.18.2

如果整数加法溢出,则结果是数学和的低阶位,如某些足够大的二进制补码格式所示.如果发生溢出,则结果的符号与两个操作数值的数学和的符号不同.

这意味着您可以依赖此行为.


Tom*_*ine 7

在大多数处理器上,算术指令无溢出故障模式.他们设置了一个必须检查的标志.这是一个额外的指令,所以可能更慢.为了使语言实现尽可能快,通常会指定语言来忽略错误并继续.对于Java,行为在JLS中指定.对于C,语言不指定行为,但现代处理器将表现为Java.

我相信有(笨拙的)Java SE 8库提出溢出以及无符号操作的建议.我相信在DSP领域很受欢迎的行为是将值限制在最大值,因此Integer.MAX_VALUE + 1 == Integer.MAX_VALUE[不是Java].

我相信未来的语言将使用任意精度的int,但暂时还没有.需要更昂贵的编译器设计才能快速运行.