简体   繁体   English

将int(-2 ^ 31..2 ^ 31-1)超出范围的长整数转换为int会发生什么?

[英]What happens when a long outside of range for int (-2^31..2^31-1) is cast to int?

I was running code in an attempt to figure out the behavior of Java when losing precision due to casting between the integral decimal numeric types, and I found an unexpected result: 我正在运行代码,试图找出由于整数十进制数字类型之间的转换而导致精度下降时Java的行为,但发现了意外的结果:

long l2 = 999999999999999999L;   //outside of range -2147483648..2147483647 for int
int i3=(int)l2;    
System.out.println(l2); //999999999999999999, as expected.
System.out.println(i3); //I expected 2147483647, but got -1486618625

Can someone please explain how I'm getting a large negative int out of a large positive long? 有人可以解释一下我如何从大正整数中得到大负整数吗? I would have expected the system to at least make a best effort casting attempt, returning the maximum positive integer (the closest valid int to the long which is too large to be stored in integer.) Instead, I'm getting a negative number which does not make sense to me. 我希望系统至少会尽最大努力进行转换尝试,返回最大正整数(最接近有效整数的长整数,该整数太大而无法存储在整数中。)相反,我得到了一个负数对我来说没有意义。

The narrowing primitive conversion of a long to an int discards all but the lower order 32 bits of the original number, so you don't get Integer.MAX_VALUE . long转换为int原始转换会舍弃原始数字的除低阶32位以外的所有位,因此您不会获得Integer.MAX_VALUE

The JLS, Section 5.1.3 , states: JLS第5.1.3节指出:

A narrowing conversion of a signed integer to an integral type T simply discards all but the n lowest order bits, where n is the number of bits used to represent type T. In addition to a possible loss of information about the magnitude of the numeric value, this may cause the sign of the resulting value to differ from the sign of the input value. 将有符号整数缩小为整数类型T会简单地丢弃除n个最低阶位以外的所有位,其中n是用于表示类型T的位数。除了可能丢失有关数值幅度的信息外, ,这可能导致结果值的符号与输入值的符号不同。

This is in contrast to a primitive narrowing conversion from a floating-point type to an int , which may result in Integer.MAX_VALUE if the original value was too big. 这与从浮点类型到int的原始缩小转换相反,如果原始值太大,则可能导致Integer.MAX_VALUE

double l2 = 999999999999999999.0;
System.out.println((int) l2);

This prints: 打印:

2147483647

Let's first take a look at the result number bits : 首先让我们看一下结果数位:

在此处输入图片说明

Now look at the bits representation of 999999999999999999 : 现在查看999999999999999999的位表示形式:

在此处输入图片说明

Notice that the first 32 bits is the same in both case. 请注意,两种情况的前32位相同。

Now considering the JLS, Section 5.1.3, as rgettman stated : 现在考虑rgettman指出的JLS,第5.1.3节:

A narrowing conversion of a signed integer to an integral type T simply discards all but the n lowest order bits, where n is the number of bits used to represent type T. In addition to a possible loss of information about the magnitude of the numeric value, this may cause the sign of the resulting value to differ from the sign of the input value. 将有符号整数缩小为整数类型T会简单地丢弃除n个最低阶位以外的所有位,其中n是用于表示类型T的位数。除了可能丢失有关数值幅度的信息外, ,这可能导致结果值的符号与输入值的符号不同。

So you would only keep the 32 first bits (10100111011000111111111111111111) when doing the cast. 因此,在进行强制转换时,您只保留前32位(10100111011000111111111111111111111)。 Therefore, considering the highest bit of a signed integer represent the sign of the number you will have a negative(1)0100111011000111111111111111111 因此,考虑到有符号整数的最高位代表数字的符号,您将得到负数(1)0100111011000111111111111111111111

Which is equals to -1486618625 as decimal value. 等于-1486618625作为十进制值。

A cast does not do any conversations nor does it care about the data. 演员表不进行任何对话,也不关心数据。 (or about truncating) (或关于截断)

999999999999999999 in binary is 0000 1101 1110 0000 1011 0110 1011 0011 1010 0111 0110 0011 1111 1111 1111 1111 . 999999999999999999二进制文件是0000 1101 1110 0000 1011 0110 1011 0011 1010 0111 0110 0011 1111 1111 1111 1111

When casting this to an signed int, just the lower 32 bits will be used: 1010 0111 0110 0011 1111 1111 1111 1111 - Now, that number means (its an signed integer now due to casting): 将其强制转换为带符号的int时,将仅使用低32位: 1010 0111 0110 0011 1111 1111 1111 1111现在,该数字表示(由于强制转换,它现在是带符号的整数):

  • Leading 1 = negative number 前导1 =负数
  • 010 0111 0110 0011 1111 1111 1111 1111 would be 660865023 in dec... not correct. 010 0111 0110 0011 1111 1111 1111 1111会是660865023 ,...不正确。
  • Java uses the Two's complement, which means if you are only looking at the "number" of a negative number, you need to invert every bit and add 1 to get the actual numeric value: Java使用二进制补码,这意味着如果仅查看负数的“数字”,则需要将每一位取反并加1以获得实际的数值:

so: 所以:

 010 0111 0110 0011 1111 1111 1111 1111 
 101 1000 1001 1100 0000 0000 0000 0000 + 1 
 101 1000 1001 1100 0000 0000 0000 0001 

101 1000 1001 1100 0000 0000 0000 0001 is 1486618625 - and it's negative: Voila, your -1486618625 101 1000 1001 1100 0000 0000 0000 00011486618625它是负数:瞧,您的-1486618625

The highest bit of a signed integer is the sign bit. 有符号整数的最高位是符号位。 So, if you overflow an operation into that bit, you will get a negative number. 因此,如果您将操作溢出到该位,则会得到一个负数。 In this case you are doing it by casting. 在这种情况下,您可以通过强制转换来实现。

= 1101 1110 0000 1011 0110 1011 0011 1010 0111 0110 0011 1111 1111 1111 1111

Truncated to (int):
                     1010 0111 0110 0011 1111 1111 1111 1111


Twos' compliment transform:

                     0101 1000 1001 1100 0000 0000 0000 0001 = 1486618625

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

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