wood burning stoves 2.0*
The moose likes Beginning Java and the fly likes cast to bytes Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of OCA/OCP Java SE 7 Programmer I & II Study Guide this week in the OCPJP forum!
JavaRanch » Java Forums » Java » Beginning Java
Bookmark "cast to bytes" Watch "cast to bytes" New topic
Author

cast to bytes

Jean John
Greenhorn

Joined: Dec 21, 2010
Posts: 24



The output is

Value of a:127

Value of b:-128

Value of c:0

I understand that casting is required after 8 bits for a byte variable and the first bit is the sign. so -128 to 127 is allowed for a byte.

I didn't get how the 128 got cast to -128 and 256 to zero.
Can someone explain the cast that happened for the variable b and c as in how the bits got clipped.


Thanks,
Jean
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3647
    
  17

Casting to a smaller integer type always just hacks off the most significant bytes.

128 in binary is 0000 1000 0000. When you lop off the first three bytes, you're left with 1000 0000, which is -128.

256 in binary is 0001 0000 0000. When you lop off the first three bytes, you're left with 0000 0000, which is 0.
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39478
    
  28
Get the Integer class to print the binary representation of those three numbers. There is a method which converts them to a binary String, unfortunately without leading 0s. You will see they are
0000_0000_0000_0000_0000_0000_0111_1111 = 127
0000_0000_0000_0000_0000_0000_1000_0000 = 128
0000_0000_0000_0000_0000_0001_0000_0000 = 256

Now you cast, which deletes the higher-order 24 bits. And you get ...
0000_0000_0000_0000_0000_0000_0111_1111 = 127
0000_0000_0000_0000_0000_0000_1000_0000 = -128
0000_0000_0000_0000_0000_0001_0000_0000 = 0

Remember you only take the lowest-order 8 bits for a byte.
Jesper de Jong
Java Cowboy
Saloon Keeper

Joined: Aug 16, 2005
Posts: 14278
    
  21

To understand exactly how this works, you have to understand that a byte in Java is an 8-bit signed integer that is stored in two's complement format. Because of this, the range of values that can be stored in a byte goes from -128 to +127.

If you have an integer value that is outside of this range and you cast it to byte, then the higher bits will be cut off the value and the lower eight bits will be interpreted as a byte. Let's look at what this means for the values you tried:

127 = 0000 0000 0000 0000 0000 0000 0111 1111 -> take lower 8 bits: 0111 1111 -> fits in the range of byte, so this will remain 127

128 = 0000 0000 0000 0000 0000 0000 1111 1111 -> take lower 8 bits: 1111 1111 -> when interpreted as a byte in two's complement, this is -128

256 = 0000 0000 0000 0000 0000 0001 0000 0000 -> take lower 8 bits: 0000 0000 -> zero

Java Beginners FAQ - JavaRanch SCJP FAQ - The Java Tutorial - Java SE 8 API documentation
Ralph Cook
Ranch Hand

Joined: May 29, 2005
Posts: 479
128 decimal is 1000 0000 binary. The highest-order bit in a signed integer is the sign, 1 for negative, 0 for positive. So you have a negative flag, but 0s in the rest of the byte. This is not a legal value in a byte, so having it print out -128 comes under the heading of "unpredictable result".

I expect what happened is that the conversion routine performed a "two's complement" on the lowest 8 bits of the value; reversing all the bits and then adding one, which in this case gives you back the same 1000 0000 value. This represents 128 in a larger integer. Then it looked at the sign to determine that you had a negative integer.

256 decimal is 1 0000 0000 binary. I expect that, in this case (as in the other case), the conversion routine first eliminated all bits past the 8th position, leaving it with 0.

You haven't asked this, but keep in mind that casting is an operation that often bypasses normal checks and produces unpredictable results. You are telling the compiler that you know what you're doing; it is just to treat this value as though it were a legal instance of the type that you're telling it. It is up to the programmer, in this case, to check things like the legality of the values being cast. Neither 1000 0000 nor 1 0000 0000 are legal values to cast to byte.

rc

edit: slight mistake; 1000 0000 is legal in a byte as -128, but casting a larger integer with 0000 0000 1000 0000 to byte does not give you the same value as the larger integer had, because the '1' is in a position that means a different thing in a byte representation.
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19723
    
  20

It all works with how bytes, ints etc are represented as bits.

128 is in bits 0000 0000 0000 0000 0000 0000 1000 0000. If you cast that to a byte you chop off everything but the last 8 bits: 1000 0000. That's -128. Check out two's complement for more information.

Likewise, 256 is 0000 0000 0000 0000 0000 0001 0000 0000. This gets turned into 0000 0000 when you cast it to a byte. That's 0.

Edit: wow, within a few minutes we have 5 times the same answer


SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6
How To Ask Questions How To Answer Questions
Ralph Cook
Ranch Hand

Joined: May 29, 2005
Posts: 479
Jesper de Jong wrote:To understand exactly how this works, you have to understand that a byte in Java is an 8-bit signed integer that is stored in two's complement format. Because of this, the range of values that can be stored in a byte goes from -128 to +127.

If you have an integer value that is outside of this range and you cast it to byte, then the higher bits will be cut off the value and the lower eight bits will be interpreted as a byte. Let's look at what this means for the values you tried:

127 = 0000 0000 0000 0000 0000 0000 0111 1111 -> take lower 8 bits: 0111 1111 -> fits in the range of byte, so this will remain 127

128 = 0000 0000 0000 0000 0000 0000 1111 1111 -> take lower 8 bits: 1111 1111 -> when interpreted as a byte in two's complement, this is -128

256 = 0000 0000 0000 0000 0000 0001 0000 0000 -> take lower 8 bits: 0000 0000 -> zero


Actually, the two's complement of 1111 1111 is 1 (reverse all bits and add one), and 1111 1111 is the legal representation of -1 in a byte.

rc
Ove Lindström
Ranch Hand

Joined: Mar 10, 2008
Posts: 326

Rob Spoor wrote:
Edit: wow, within a few minutes we have 5 times the same answer


This phenomenon is called "Forum Drag Race". You compete in 1/4mile (questions that are over 402 character) and 1/8 mile (question that are 201 characters).
Jean John
Greenhorn

Joined: Dec 21, 2010
Posts: 24

Its really clear now.. and thanks for the multiple help
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39478
    
  28
Ralph Cook wrote:. . . The highest-order bit in a signed integer is the sign, 1 for negative, 0 for positive. . . .
Afraid not. That is S&M numbering you are thinking of. S&M means sign and magnitude, which is usually only used for floating point numbers, including the IEEE754 format.
The 1 at the most-significant bit in a two’s complement integer does not represent a minus sign. It is a value bit, representing (in a byte, where it is bit no 7), minus128. In a short, it would be minus35768. The following 111_1111 in a byte can never add up to more than 127, so a number with 1 at its first position is always negative.
Jesper de Jong
Java Cowboy
Saloon Keeper

Joined: Aug 16, 2005
Posts: 14278
    
  21

You're right Campbell, but Ralph is also sort-of right; you can still see the sign of a two's complement number by looking at the leftmost bit: 0 = positive, 1 = negative.
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39478
    
  28
I take your point, Jesper.
But I would also disagree with him about casting being unpredictable. It is very deterministic, and we have shown how it works. So the results are predictable, but may be very wrong for the purposes we want.
Ralph Cook
Ranch Hand

Joined: May 29, 2005
Posts: 479
I was only sort-of right; CR's explanation is more complete. It isn't really a sign bit the way floating-point sign bits are. Thanks for the correction.

I guess I meant it is unpredictable UNLESS you understand everything that goes under the covers. Most people aren't going to struggle through even one paragraph of the Java Specification on "Narrowing Primitive Conversions", much less predict that casting 128 to byte ends up as -128. If all you wanted to do was get the int value into a byte, THAT would surprise most people.

rc
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 39478
    
  28
Ralph Cook wrote: . . . It isn't really a sign bit the way floating-point sign bits are. . . .
Agreed. Even though the wikipedia article about two’s complement uses the term “sign bit”.

There are at least four formats for binary integers:
  • 1: Unsigned.
  • 2: S&M (=sign & magnitude)
  • 3: Excess 128 (for bytes), excess 32768 (for 16 bits) etc.
  • 4: Two’s complement.
  • I have only ever seen two’s complement and unsigned used. I don’t know whether one’s complement was ever used for number values.
    Campbell Ritchie
    Sheriff

    Joined: Oct 13, 2005
    Posts: 39478
        
      28
    And you were at least sort-of right; you meant to say that although the leftmost bit isn't really a sign bit, all two’s complement numbers with a 1 at their extreme left are negative.
     
    It is sorta covered in the JavaRanch Style Guide.
     
    subject: cast to bytes