简体   繁体   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);

is true.是真的。

I understand that integer in Java is 32 bit and can't go above 2 31 -1, but I can't understand why adding 1 to its MAX_VALUE results in MIN_VALUE and not in some kind of exception.我知道 Java 中的整数是 32 位,不能超过 2 31 -1,但我不明白为什么在其MAX_VALUE加 1 会导致MIN_VALUE而不是某种异常。 Not mentioning something like transparent conversion to a bigger type, like Ruby does.没有提到像 Ruby 那样透明转换为更大类型的事情。

Is this behavior specified somewhere?这种行为是否在某处指定? Can I rely on it?我可以依赖它吗?

Because the integer overflows.因为整数溢出。 When it overflows, the next value is Integer.MIN_VALUE .当它溢出时,下一个值是Integer.MIN_VALUE Relevant JLS 相关JLS

If an integer addition overflows, then the result is the low-order bits of the mathematical sum as represented in some sufficiently large two's-complement format.如果整数加法溢出,则结果是数学和的低位,以某种足够大的二进制补码格式表示。 If overflow occurs, then the sign of the result is not the same as the sign of the mathematical sum of the two operand values.如果发生溢出,则结果的符号与两个操作数值的数学和的符号不同。

The integer storage gets overflowed and that is not indicated in any way, as stated in JSL 3rd Ed. 正如 JSL 第 3 版中所述,整数存储溢出,并且没有以任何方式指示。 :

The built-in integer operators do not indicate overflow or underflow in any way.内置整数运算符不以任何方式指示上溢或下溢。 Integer operators can throw a NullPointerException if unboxing conversion (§5.1.8) of a null reference is required.如果需要空引用的拆箱转换(第 5.1.8 节) ,则整数运算符可能会抛出NullPointerException Other than that, the only integer operators that can throw an exception (§11) are the integer divide operator / (§15.17.2) and the integer remainder operator % (§15.17.3) , which throw an ArithmeticException if the right-hand operand is zero, and the increment and decrement operators ++ ( §15.15.1 , §15.15.2 ) and -- ( §15.14.3 , §15.14.2 ), which can throw an OutOfMemoryError if boxing conversion (§5.1.7) is required and there is not sufficient memory available to perform the conversion.除此之外,唯一的整数,可以抛出异常运营商(§11)是整数除法运算/ (§15.17.2)和整数余数运算符% (§15.17.3) ,其抛出ArithmeticException如果右手操作数为零,并且递增和递减运算符++ (第15.15.1 节,第15.15.2 节)和-- (第15.14.3 节,第15.14.2 节),如果装箱转换(第5.1 节)可能会抛出OutOfMemoryError .7)是必需的,并且没有足够的可用内存来执行转换。

Example in a 4-bits storage: 4 位存储中的示例:

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

MAX_INT + 1: MAX_INT + 1:

 0111+
 0001
 ----
 1000

You must understand how integer values are represented in binary form, and how binary addition works.您必须了解整数值如何以二进制形式表示,以及二进制加法的工作原理。 Java uses a representation called two's complement, in which the first bit of the number represents its sign. Java 使用一种称为二进制补码的表示,其中数字的第一位表示其符号。 Whenever you add 1 to the largest java Integer, which has a bit sign of 0, then its bit sign becomes 1 and the number becomes negative.每当您将 1 与位符号为 0 的最大 java Integer 相加时,它的位符号将变为 1,并且该数字变为负数。

This links explains with more details: http://www.cs.grinnell.edu/~rebelsky/Espresso/Readings/binary.html#integers-in-java这个链接解释了更多细节: http : //www.cs.grinnell.edu/~rebelsky/Espresso/Readings/binary.html#integers-in-java

-- ——

The Java Language Specification treats this behavior here: http://docs.oracle.com/javase/specs/jls/se6/html/expressions.html#15.18.2 Java 语言规范在此处处理此行为: http : //docs.oracle.com/javase/specs/jls/se6/html/expressions.html#15.18.2

If an integer addition overflows, then the result is the low-order bits of the mathematical sum as represented in some sufficiently large two's-complement format.如果整数加法溢出,则结果是数学和的低位,以某种足够大的二进制补码格式表示。 If overflow occurs, then the sign of the result is not the same as the sign of the mathematical sum of the two operand values.如果发生溢出,则结果的符号与两个操作数值的数学和的符号不同。

Which means that you can rely on this behavior.这意味着您可以依赖此行为。

On most processors, the arithmetic instructions have no mode to fault on an overflow.在大多数处理器上,算术指令在溢出时没有故障模式。 They set a flag that must be checked.他们设置了一个必须检查的标志。 That's an extra instruction so probably slower.这是一个额外的指令,所以可能会更慢。 In order for the language implementations to be as fast as possible, the languages are frequently specified to ignore the error and continue.为了使语言实现尽可能快,语言经常被指定为忽略错误并继续。 For Java the behaviour is specified in the JLS .对于 Java,行为在JLS 中指定。 For C, the language does not specify the behaviour, but modern processors will behave as Java.对于 C,该语言没有指定行为,但现代处理器的行为与 Java 相同。

I believe there are proposals for (awkward) Java SE 8 libraries to throw on overflow, as well as unsigned operations.我相信有关于(尴尬的)Java SE 8 库的建议可以抛出溢出,以及未签名的操作。 A behaviour, I believe popular in the DSP world, is clamp the values at the maximums, so Integer.MAX_VALUE + 1 == Integer.MAX_VALUE [not Java].我相信在 DSP 世界中流行的一种行为是将值限制在最大值,因此Integer.MAX_VALUE + 1 == Integer.MAX_VALUE [不是 Java]。

I'm sure future languages will use arbitrary precision ints, but not for a while yet.我确信未来的语言将使用任意精度整数,但暂时还不会。 Requires more expensive compiler design to run quickly.需要更昂贵的编译器设计才能快速运行。

The same reason why the date changes when you cross the international date line: there's a discontinuity there.当您越过国际日期变更线时日期发生变化的原因相同:那里存在不连续性。 It's built into the nature of binary addition.它内置于二进制加法的性质中。

This is a well known issue related to the fact that Integers are represented as two's complement down at the binary layer.这是一个众所周知的问题,与整数在二进制层表示为二进制 补码的事实有关。 When you add 1 to the max value of a two's complement number you get the min value.当您将二进制补码数的最大值加 1 时,您会得到最小值。 Honestly, all integers behaved this way before java existed, and changing this behavior for the Java language would have added more overhead to integer math, and confused programmers coming from other languages.老实说,在 java 出现之前,所有整数都是这种行为,而为 Java 语言改变这种行为会增加整数数学的开销,并使来自其他语言的程序员感到困惑。

When you add 3 (in binary 11 ) to 1 (in binary 1 ), you must change to 0 (in binary 0 ) all binary 1 starting from the right, until you got 0, which you should change to 1 .当您将3 (二进制11 )加到 1(二进制1 )时,您必须将所有二进制1从右侧开始更改为0 (二进制0 ),直到得到 0,您应该将其更改为1 Integer.MAX_VALUE has all places filled up with 1 so there remain only 0 s. Integer.MAX_VALUE所有位置都填充了1因此只剩下0秒。

Easy to understand with byte example=>易于理解的字节示例=> 在此处输入图片说明

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

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

Here we are forcing addition and casting it to be treated as byte.在这里,我们强制添加并将其转换为字节。 So what will happen is that when we reach 127 (largest possible value for a byte) and we add plus 1 then the value flips (as shown in image) from 127 and it becomes -128.那么将会发生的情况是,当我们达到 127(一个字节的最大可能值)并加上 1 时,该值从 127 翻转(如图所示)并变为 -128。 The value starts circling around the type.该值开始围绕该类型盘旋。

Same is for integer.整数也是如此。

Also integer + integer stays integer ( unlike byte + byte which gets converted to int [unless casted forcefully as above]).此外,整数 + 整数保持整数(与字节 + 字节不同,后者被转换为 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);

Cause overflow and two-compliant nature count goes on "second loop", we was on far most right position 2147483647 and after summing 1, we appeared at far most left position -2147483648, next incrementing goes -2147483647, -2147483646, -2147483645, ... and so forth to the far most right again and on and on, its nature of summing machine on this bit depth.导致溢出和双兼容自然计数继续“第二次循环”,我们在最右边的位置 2147483647 和 1 后,我们出现在最左边的位置 -2147483648,下一个递增是 -2147483647, -2147483646, -214574836 ... 以此类推,直到最右边,它在这个位深度上的求和机的性质。

Some examples:一些例子:

int a = 2147483647;

System.out.println(a);

gives: 2147483647给:2147483647

System.out.println(a+1);

gives: -2147483648 (cause overflow and two-compliant nature count goes on "second loop", we was on far most right position 2147483647 and after summing 1, we appeared at far most left position -2147483648, next incrementing goes -2147483648, -2147483647, -2147483646, ... and so fores to the far most right again and on and on, its nature of summing machine on this bit depth)给出:-2147483648(因为溢出和符合两个性质的计数进入“第二个循环”,我们在最右边的位置 2147483647 和 1 后,我们出现在最左边的位置 -2147483648,下一个增量是 -2147483648,- 2147483647、-2147483646、...等等,一次又一次地向最右边推进,它在这个位深度上的求和机的性质)

System.out.println(2-a); 

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

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

gives: 2147483647 (-2147483647-1 -> -2147483648, -2147483648-1 -> 2147483647 some loop described in previous answers)给出:2147483647(-2147483647-1 -> -2147483648, -2147483648-1 -> 2147483647 之前答案中描述的一些循环)

System.out.println(2*a);

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

System.out.println(4*a);

gives: -4 (2147483647+2147483647+2147483647+2147483647 -> -2147483648+2147483646+2147483647+2147483647 -> -2-2 (according to last answer) -> -4)`给出:-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