繁体   English   中英

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

[英]why Integer.MAX_VALUE + 1 == Integer.MIN_VALUE?

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

是真的。

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

这种行为是否在某处指定? 我可以依赖它吗?

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

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

正如 JSL 第 3 版中所述,整数存储溢出,并且没有以任何方式指示。

内置整数运算符不以任何方式指示上溢或下溢。 如果需要空引用的拆箱转换(第 5.1.8 节) ,则整数运算符可能会抛出NullPointerException 除此之外,唯一的整数,可以抛出异常运营商(§11)是整数除法运算/ (§15.17.2)和整数余数运算符% (§15.17.3) ,其抛出ArithmeticException如果右手操作数为零,并且递增和递减运算符++ (第15.15.1 节,第15.15.2 节)和-- (第15.14.3 节,第15.14.2 节),如果装箱转换(第5.1 节)可能会抛出OutOfMemoryError .7)是必需的,并且没有足够的可用内存来执行转换。

4 位存储中的示例:

MAX_INT: 0111 (7)
MIN_INT: 1000 (-8)

MAX_INT + 1:

 0111+
 0001
 ----
 1000

您必须了解整数值如何以二进制形式表示,以及二进制加法的工作原理。 Java 使用一种称为二进制补码的表示,其中数字的第一位表示其符号。 每当您将 1 与位符号为 0 的最大 java Integer 相加时,它的位符号将变为 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

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

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

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

我相信有关于(尴尬的)Java SE 8 库的建议可以抛出溢出,以及未签名的操作。 我相信在 DSP 世界中流行的一种行为是将值限制在最大值,因此Integer.MAX_VALUE + 1 == Integer.MAX_VALUE [不是 Java]。

我确信未来的语言将使用任意精度整数,但暂时还不会。 需要更昂贵的编译器设计才能快速运行。

当您越过国际日期变更线时日期发生变化的原因相同:那里存在不连续性。 它内置于二进制加法的性质中。

这是一个众所周知的问题,与整数在二进制层表示为二进制 补码的事实有关。 当您将二进制补码数的最大值加 1 时,您会得到最小值。 老实说,在 java 出现之前,所有整数都是这种行为,而为 Java 语言改变这种行为会增加整数数学的开销,并使来自其他语言的程序员感到困惑。

当您将3 (二进制11 )加到 1(二进制1 )时,您必须将所有二进制1从右侧开始更改为0 (二进制0 ),直到得到 0,您应该将其更改为1 Integer.MAX_VALUE所有位置都填充了1因此只剩下0秒。

易于理解的字节示例=> 在此处输入图片说明

byte a=127;//max value for byte
byte b=1;

byte c=(byte) (a+b);//assigns -128
System.out.println(c);//prints -128

在这里,我们强制添加并将其转换为字节。 那么将会发生的情况是,当我们达到 127(一个字节的最大可能值)并加上 1 时,该值从 127 翻转(如图所示)并变为 -128。 该值开始围绕该类型盘旋。

整数也是如此。

此外,整数 + 整数保持整数(与字节 + 字节不同,后者被转换为 int [除非如上所述强制转换])。

int int1=Integer.MAX_VALUE+1;
System.out.println(int1); //prints -2147483648
System.out.println(Integer.MIN_VALUE); //prints -2147483648

//below prints 128 as converted to int as not forced with casting
System.out.println(Byte.MAX_VALUE+1);

导致溢出和双兼容自然计数继续“第二次循环”,我们在最右边的位置 2147483647 和 1 后,我们出现在最左边的位置 -2147483648,下一个递增是 -2147483647, -2147483646, -214574836 ... 以此类推,直到最右边,它在这个位深度上的求和机的性质。

一些例子:

int a = 2147483647;

System.out.println(a);

给:2147483647

System.out.println(a+1);

给出:-2147483648(因为溢出和符合两个性质的计数进入“第二个循环”,我们在最右边的位置 2147483647 和 1 后,我们出现在最左边的位置 -2147483648,下一个增量是 -2147483648,- 2147483647、-2147483646、...等等,一次又一次地向最右边推进,它在这个位深度上的求和机的性质)

System.out.println(2-a); 

给出:-2147483645(-2147483647+2 似乎是数学逻辑)

System.out.println(-2-a);

给出:2147483647(-2147483647-1 -> -2147483648, -2147483648-1 -> 2147483647 之前答案中描述的一些循环)

System.out.println(2*a);

给出:-2(2147483647+2147483647 -> -2147483648+2147483646 又是数学逻辑)

System.out.println(4*a);

给出:-4 (2147483647+2147483647+2147483647+2147483647 -> -2147483648+2147483646+2147483647+2147483647) ->cord -> 最后一个答案 ->-2`

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM