[java] Odd behavior when Java converts int to byte?

int i =132;

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

Mindboggling. Why is the output -124?

This question is related to java

The answer is


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.


often in books you will find the explanation of casting from int to byte as being performed by modulus division. this is not strictly correct as shown below what actually happens is the 24 most significant bits from the binary value of the int number are discarded leaving confusion if the remaining leftmost bit is set which designates the number as negative

public class castingsample{

public static void main(String args[]){

    int i;
    byte y;
    i = 1024;
    for(i = 1024; i > 0; i-- ){

      y = (byte)i;
      System.out.print(i + " mod 128 = " + i%128 + " also ");
      System.out.println(i + " cast to byte " + " = " + y);

    }

}

}

132 in digits (base 10) is 1000_0100 in bits (base 2) and Java stores int in 32 bits:

0000_0000_0000_0000_0000_0000_1000_0100

Algorithm for int-to-byte is left-truncate; Algorithm for System.out.println is two's-complement (Two's-complement is if leftmost bit is 1, interpret as negative one's-complement (invert bits) minus-one.); Thus System.out.println(int-to-byte( )) is:

  • interpret-as( if-leftmost-bit-is-1[ negative(invert-bits(minus-one(] left-truncate(0000_0000_0000_0000_0000_0000_1000_0100) [)))] )
  • =interpret-as( if-leftmost-bit-is-1[ negative(invert-bits(minus-one(] 1000_0100 [)))] )
  • =interpret-as(negative(invert-bits(minus-one(1000_0100))))
  • =interpret-as(negative(invert-bits(1000_0011)))
  • =interpret-as(negative(0111_1100))
  • =interpret-as(negative(124))
  • =interpret-as(-124)
  • =-124   Tada!!!

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.


here is a very mechanical method without the distracting theories:

  1. Convert the number into binary representation (use a calculator ok?)
  2. Only copy the rightmost 8 bits (LSB) and discard the rest.
  3. From the result of step#2, if the leftmost bit is 0, then use a calculator to convert the number to decimal. This is your answer.
  4. Else (if the leftmost bit is 1) your answer is negative. Leave all rightmost zeros and the first non-zero bit unchanged. And reversed the rest, that is, replace 1's by 0's and 0's by 1's. Then use a calculator to convert to decimal and append a negative sign to indicate the value is negative.

This more practical method is in accordance to the much theoretical answers above. So, those still reading those Java books saying to use modulo, this is definitely wrong since the 4 steps I outlined above is definitely not a modulo operation.


Two's complement Equation:

enter image description here


In Java, byte (N=8) and int (N=32) are represented by the 2s-complement shown above.

From the equation, a7 is negative for byte but positive for int.

coef:   a7    a6  a5  a4  a3  a2  a1  a0
Binary: 1     0   0   0   0   1   0   0
----------------------------------------------
int:    128 + 0 + 0 + 0 + 0 + 4 + 0 + 0 =  132
byte:  -128 + 0 + 0 + 0 + 0 + 4 + 0 + 0 = -124

 N is input number
case 1: 0<=N<=127  answer=N;
case 2: 128<=N<=256 answer=N-256 
case 3: N>256   
        temp1=N/256;
        temp2=N-temp*256;
        if temp2<=127   then answer=temp2;
        else if temp2>=128  then answer=temp2-256;
case 4: negative  number input
        do same procedure.just change the sign of the solution           

  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

A quick algorithm that simulates the way that it work is the following:

public int toByte(int number) {
    int tmp = number & 0xff
    return (tmp & 0x80) == 0 ? tmp : tmp - 256;
}

How this work ? Look to daixtr answer. A implementation of exact algorithm discribed in his answer is the following:

public static int toByte(int number) {
    int tmp = number & 0xff;
    if ((tmp & 0x80) == 0x80) {
        int bit = 1;
        int mask = 0;
        for(;;) {
            mask |= bit;
            if ((tmp & bit) == 0) {
                bit <<=1;
                continue;
            }
            int left = tmp & (~mask);
            int right = tmp & mask;
            left = ~left;
            left &= (~mask);
            tmp = left | right;
            tmp = -(tmp & 0xff);
            break;
        }
    }
    return tmp;
}

Conceptually, repeated subtractions of 256 are made to your number, until it is in the range -128 to +127. So in your case, you start with 132, then end up with -124 in one step.

Computationally, this corresponds to extracting the 8 least significant bits from your original number. (And note that the most significant bit of these 8 becomes the sign bit.)

Note that in other languages this behaviour is not defined (e.g. C and C++).