使用二进制文字

时间:2018-01-18 19:03:42

标签: java

请考虑以下代码:

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_VALUE2147483647,编译器接受该范围内的任何int,并在此值超出2147483647时抛出错误。但是,上面代码段中的int x3(int:-1,long:2147483648)和x4(int:-1,long:4294967295)被接受,没有任何错误,但在{的情况下抛出错误{1}}。

第一个问题:为什么编译器没有抱怨x5的范围?

第二个问题:如果接受x3x3的值没有任何错误,为什么在x4的情况下会抛出错误?

4 个答案:

答案 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_00000b1111_1111_1111_1111_1111_1111_1111_1111以及它们的十六进制对应0x80_00_00_000xFF_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)

x3x4的第一位是1,因此它们被视为负数。它们都被声明为32位数字,因此它们符合int数据类型,并且编译器不会抱怨。 x5给出错误,因为您试图将33位分配给32位数据类型,因此它会溢出。

答案 2 :(得分:0)

原始int是一个32位数字,前导位是整数的符号,因此当您使用int作为2147483648时,会导致溢出错误。要解决您的问题,请使用原语doublelong获取更高的值。

答案 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”?

的好答案

3.10.1. Integer Literals中显示:

  

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位,则为编译时错误。