Odd behavior when Java converts int to byte?

Viewed 293912
int i =132;

byte b =(byte)i; System.out.println(b);

Mindboggling. Why is the output -124?

12 Answers

In Java, an int is 32 bits. A byte is 8 bits .

Most primitive types in Java are signed, and byte, short, int, and long are encoded in two's complement. (The char type is unsigned, and the concept of a sign is not applicable to boolean.)

In this number scheme the most significant bit specifies the sign of the number. If more bits are needed, the most significant bit ("MSB") is simply copied to the new MSB.

So if you have byte 255: 11111111 and you want to represent it as an int (32 bits) you simply copy the 1 to the left 24 times.

Now, one way to read a negative two's complement number is to start with the least significant bit, move left until you find the first 1, then invert every bit afterwards. The resulting number is the positive version of that number

For example: 11111111 goes to 00000001 = -1. This is what Java will display as the value.

What you probably want to do is know the unsigned value of the byte.

You can accomplish this with a bitmask that deletes everything but the least significant 8 bits. (0xff)

So:

byte signedByte = -1;
int unsignedByte = signedByte & (0xff);

System.out.println("Signed: " + signedByte + " Unsigned: " + unsignedByte);

Would print out: "Signed: -1 Unsigned: 255"

What's actually happening here?

We are using bitwise AND to mask all of the extraneous sign bits (the 1's to the left of the least significant 8 bits.) When an int is converted into a byte, Java chops-off the left-most 24 bits

1111111111111111111111111010101
&
0000000000000000000000001111111
=
0000000000000000000000001010101

Since the 32nd bit is now the sign bit instead of the 8th bit (and we set the sign bit to 0 which is positive), the original 8 bits from the byte are read by Java as a positive value.

byte in Java is signed, so it has a range -2^7 to 2^7-1 - ie, -128 to 127. Since 132 is above 127, you end up wrapping around to 132-256=-124. That is, essentially 256 (2^8) is added or subtracted until it falls into range.

For more information, you may want to read up on two's complement.

132 is outside the range of a byte which is -128 to 127 (Byte.MIN_VALUE to Byte.MAX_VALUE) Instead the top bit of the 8-bit value is treated as the signed which indicates it is negative in this case. So the number is 132 - 256 = -124.

If you want to understand this mathematically, like how this works

so basically numbers b/w -128 to 127 will be written same as their decimal value, above that its (your number - 256).

eg. 132, the answer will be 132 - 256 = - 124 i.e.

256 + your answer in the number 256 + (-124) is 132

Another Example

double a = 295.04;
int b = 300;
byte c = (byte) a;
byte d = (byte) b; System.out.println(c + " " + d);

the Output will be 39 44

(295 - 256) (300 - 256)

NOTE: it won't consider numbers after the decimal.

  1. In java int takes 4 bytes=4x8=32 bits
  2. byte = 8 bits range=-128 to 127

converting 'int' into 'byte' is like fitting big object into small box

if sign in -ve takes 2's complement

example 1: let number be 130

step 1:130 interms of bits =1000 0010

step 2:condider 1st 7 bits and 8th bit is sign(1=-ve and =+ve)

step 3:convert 1st 7 bits to 2's compliment

            000 0010   
          -------------
            111 1101
       add         1
          -------------
            111 1110 =126

step 4:8th bit is "1" hence the sign is -ve

step 5:byte of 130=-126

Example2: let number be 500

step 1:500 interms of bits 0001 1111 0100

step 2:consider 1st 7 bits =111 0100

step 3: the remained bits are '11' gives -ve sign

step 4: take 2's compliment

        111 0100
      -------------
        000 1011 
    add        1
      -------------
        000 1100 =12

step 5:byte of 500=-12

example 3: number=300

 300=1 0010 1100

 1st 7 bits =010 1100

 remaining bit is '0' sign =+ve need not take 2's compliment for +ve sign

 hence 010 1100 =44

 byte(300) =44
Related