请考虑以下代码:
int x1 = 0b1111_1111_1111_1111_1111_1111_1111_111; // binary for 2147483647
System.out.println(x1); // prints 2147483647
int x2 = 2147483648; // The literal 2147483648 of type int is out of range
// x3 is binary representation for 2147483648
int x3 = 0b1000_0000_0000_0000_0000_0000_0000_0000; // accepted without any compile errors
System.out.println(x3); // prints -2147483648
// x4 is binary representation for 4294967295
int x4 = 0b1111_1111_1111_1111_1111_1111_1111_1111; // long value: 4294967295
System.out.println(x4); // prints -1
int x5 = 0b1111_1111_1111_1111_1111_1111_1111_1111_1; // The literal 0b1111_1111_1111_1111_1111_1111_1111_1111_1 of type int is out of range
Integer.MAX_VALUE
为2147483647
,编译器接受该范围内的任何int
,并在此值超出2147483647
时抛出错误。但是,上面代码段中的int x3
(int:-1,long:2147483648)和x4
(int:-1,long:4294967295)被接受,没有任何错误,但在{的情况下抛出错误{1}}。
第一个问题:为什么编译器没有抱怨x5
的范围?
第二个问题:如果接受x3
和x3
的值没有任何错误,为什么在x4
的情况下会抛出错误?
答案 0 :(得分:2)
<强> TL; DR 强>
为什么编译器没有抱怨x3的范围?
因为它适合32位,并且Java语言规范(JLS)说文字在有效时是有效的。
如果接受x3和x4的值没有任何错误,为什么在x5的情况下会抛出错误?
因为它不是32位,所以它是33位长。
评论代码风格
您应该将_
分隔符插入nibble边界所在的二进制文字中,而不是0b1111_1111_1111_1111_1111_1111_1111_111
它应该是0b111_1111_1111_1111_1111_1111_1111_1111
。
然后正确地表示它是第一个缺少数字的半字节。它还使其直接与十六进制表示相当,例如0x7F_FF_FF_FF
。
您插入_
的方式非常混乱。
答案很长
在Java中,使用Integer.toBinaryString(int i)
,Integer.toHexString(int i)
和Integer.toOctalString(int i)
格式化的数字格式为 unsigned 数字。
这符合JLS 3.10.1. Integer Literals定义的Java整数文字语法,其中声明:
如果十六进制,八进制或二进制
int
字面值不适合32位,则为编译时错误。
由于0b1000_0000_0000_0000_0000_0000_0000_0000
和0b1111_1111_1111_1111_1111_1111_1111_1111
以及它们的十六进制对应0x80_00_00_00
和0xFF_FF_FF_FF
全部符合32位,因此它们是有效的int
文字。
如果使用上述方法打印它们,它们与文字相匹配,即使它们打印为{(1)}(如果打印为(带符号)十进制):
-1
System.out.println(Integer.toBinaryString(0b1111_1111_1111_1111_1111_1111_1111_1111));
System.out.println(Integer.toOctalString(037_777_777_777));
System.out.println(Integer.toHexString(0xFF_FF_FF_FF));
答案 1 :(得分:1)
x3
和x4
的第一位是1
,因此它们被视为负数。它们都被声明为32位数字,因此它们符合int
数据类型,并且编译器不会抱怨。 x5
给出错误,因为您试图将33位分配给32位数据类型,因此它会溢出。
答案 2 :(得分:0)
原始int
是一个32位数字,前导位是整数的符号,因此当您使用int作为2147483648
时,会导致溢出错误。要解决您的问题,请使用原语double
或long
获取更高的值。
答案 3 :(得分:0)
The Java Language Specification有答案。
4.2. Primitive Types and Values
整数类型是byte,short,int和long,其值为8位,16位,32位和64位有符号二进制补码整数
因此int
是32位two's-complement。 (另请阅读关于:What is “2's Complement”?)
int类型的最大正十六进制,八进制和二进制文字 - 每个都代表十进制值2147483647(2 ^ 31-1) - 分别是:
- 0x7fff_ffff,
- 0177_7777_7777,
- 0b0111_1111_1111_1111_1111_1111_1111_1111
int类型的最负十六进制,八进制和二进制文字 - 每个表示十进制值-2147483648(-2 ^ 31) - 分别为:
- 0x8000_0000,
- 0200_0000_0000,
- 0b1000_0000_0000_0000_0000_0000_0000_0000
以下十六进制,八进制和二进制文字表示十进制值-1:
- 0xffff_ffff,
- 0377_7777_7777,
- 0b1111_1111_1111_1111_1111_1111_1111_1111
如果十六进制,八进制或二进制int文字不适合32位,则为编译时错误。