• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • paul wheaton
  • Liutauras Vilda
  • Ron McLeod
Sheriffs:
  • Jeanne Boyarsky
  • Devaka Cooray
  • Paul Clapham
Saloon Keepers:
  • Scott Selikoff
  • Tim Holloway
  • Piet Souris
  • Mikalai Zaikin
  • Frits Walraven
Bartenders:
  • Stephan van Hulst
  • Carey Brown

cast to bytes

 
Greenhorn
Posts: 24
Android Eclipse IDE Java
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


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
 
Bartender
Posts: 15737
368
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Marshal
Posts: 80088
412
  • Likes 3
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Java Cowboy
Posts: 16084
88
Android Scala IntelliJ IDE Spring Java
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
 
Ranch Hand
Posts: 479
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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.
 
Sheriff
Posts: 22817
132
Eclipse IDE Spring Chrome Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
 
Ralph Cook
Ranch Hand
Posts: 479
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
 
Ranch Hand
Posts: 326
Android Mac OS X Firefox Browser
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 24
Android Eclipse IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Its really clear now.. and thanks for the multiple help
 
Campbell Ritchie
Marshal
Posts: 80088
412
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 16084
88
Android Scala IntelliJ IDE Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Marshal
Posts: 80088
412
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 479
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Marshal
Posts: 80088
412
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
    Marshal
    Posts: 80088
    412
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    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.
     
    Lasagna is spaghetti flvored cake. Just like this tiny ad:
    We need your help - Coderanch server fundraiser
    https://coderanch.com/wiki/782867/Coderanch-server-fundraiser
    reply
      Bookmark Topic Watch Topic
    • New Topic