![](/img/trans.png)
[英]BitSet is not working for Integer.MAX_VALUE and 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.