-1

Consider the following code:

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 

The Integer.MAX_VALUE is 2147483647 and compiler accepts any int in that range, and throws an error when this value goes beyond 2147483647. However, the int x3(int: -1, long: 2147483648) and x4(int: -1, long: 4294967295) in above snippet is accepted without any errors but throws errors in case of x5.

First question: Why the compiler did not complain about the range of x3?

Second question: If the value of x3 and x4 is accepted without any errors, why does it throw errors in case of x5?

Aniket Sahrawat
  • 12,410
  • 3
  • 41
  • 67
  • 1
    `int` is in java a 32-bit signed [two's-complement](https://en.wikipedia.org/wiki/Two%27s_complement) integer. You can read more about this in [The Java Language Specification](https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.1-700) – Edwardth Jan 18 '18 at 19:28

4 Answers4

3

TL;DR

Why the compiler did not complain about the range of x3?

Because it fits in 32 bits, and the Java Language Specification (JLS) says that literal is valid when it does.

If the value of x3 and x4 is accepted without any errors, why does it throw errors in case of x5?

Because it doesn't fits in 32 bits, given that it is 33 bits long.


Comment on Code Style

You should insert the _ separators in a binary literal where the nibble boundaries are, so instead of 0b1111_1111_1111_1111_1111_1111_1111_111 it should be 0b111_1111_1111_1111_1111_1111_1111_1111.

That then correctly represents that it is the first nibble that's missing a digit. It also makes it directly comparable to the hex representation, e.g. 0x7F_FF_FF_FF.

Your way of inserting _ is very confusing.


Long answer

In Java, numbers formatted using Integer.toBinaryString​(int i), Integer.toHexString​(int i), and Integer.toOctalString​(int i) are formatted as unsigned numbers.

This fits the Java integer literal syntax as defined by JLS 3.10.1. Integer Literals, which states:

It is a compile-time error if a hexadecimal, octal, or binary int literal does not fit in 32 bits.

Since 0b1000_0000_0000_0000_0000_0000_0000_0000 and 0b1111_1111_1111_1111_1111_1111_1111_1111, as well as their hex counterparts 0x80_00_00_00 and 0xFF_FF_FF_FF, all fit in 32 bits, they are valid int literals.

If you print them using the methods above, they match the literal, even though they would all print -1 if printed as a (signed) decimal:

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));
11111111111111111111111111111111
37777777777
ffffffff
Community
  • 1
  • 1
Andreas
  • 154,647
  • 11
  • 152
  • 247
  • The only part that is missing in this answer is why does `x3` and `x4` have negative values. – Edwardth Jan 18 '18 at 20:11
  • @Edwardth Not missing in answer, since it wasn't asked for in question. – Andreas Jan 18 '18 at 20:14
  • @Andreas it's not directly asked, but you can see that the asker is a bit confused about the fact that the binary representation of `4294967295` doesn't throw an exception, since it seems like the value goes beyond `2147483647` and this should throw one. – Edwardth Jan 18 '18 at 20:28
2

The first bit for both x3 and x4 is 1, hence they are treated as negative numbers. They are both declared as 32 bit numbers, so they fit an int data type and the compiler doesn't complain. x5 gives error because you are attempting to assign 33 bits to a 32 bit data type, so it overflows.

BackSlash
  • 21,927
  • 22
  • 96
  • 136
0

The primitive int is a 32 bit number, with the leading bit being the sign of the integer, so when you used int for 2147483648 you caused an overflow error. To fix your problem, use the primitives double or long for higher values.

0

The Java Language Specification has the answer.

4.2. Primitive Types and Values

The integral types are byte, short, int, and long, whose values are 8-bit, 16-bit, 32-bit and 64-bit signed two's-complement integers

So int is a 32-bit two's-complement. (Also read the great answer about: What is “2's Complement”?)

And in 3.10.1. Integer Literals it shows:

The largest positive hexadecimal, octal, and binary literals of type int - each of which represents the decimal value 2147483647 (2^31-1) - are respectively:

  • 0x7fff_ffff,
  • 0177_7777_7777, and
  • 0b0111_1111_1111_1111_1111_1111_1111_1111

The most negative hexadecimal, octal, and binary literals of type int - each of which represents the decimal value -2147483648 (-2^31) - are respectively:

  • 0x8000_0000,
  • 0200_0000_0000, and
  • 0b1000_0000_0000_0000_0000_0000_0000_0000

The following hexadecimal, octal, and binary literals represent the decimal value -1:

  • 0xffff_ffff,
  • 0377_7777_7777, and
  • 0b1111_1111_1111_1111_1111_1111_1111_1111

It is a compile-time error if a hexadecimal, octal, or binary int literal does not fit in 32 bits.

Edwardth
  • 697
  • 1
  • 4
  • 14