0

I wrote a small demo for myself for better understanding of shifting a byte values. So I've byte 'd' with value 127:

class Demo {
    public static void main (String args[]) {

        byte d = 127; // 8-bit is equal to 0 111 1111

and what I try to do is to shift it in a value of 2 to the left:

int e = d << 2; /* 32-bit shifted value is equal to 0 000 0000 0000 0000 0000 0001 1111 1100
    0 * 2^0 + 0 * 2^1 + 1 * 2^2 + 1 * 2^3 + 1 * 2^4 + 1 * 2^5 + 1 * 2^6 + 1 * 2^7 + 1 * 2^8 = 
    0 * 1   + 0 * 2   + 1 * 4   + 1 * 8   + 1 * 16  + 1 * 32  + 1 * 64  + 1 * 128 + 1 * 256 = 
    0       + 0       + 4       + 8       + 16      + 32      + 64      + 128     + 256     = 508
*/

Please let me know if my logic in comments is correct, cause it's first time for me of doing such a things. So the real question is about memory allocation once I try to cast 'e' back to byte:

byte f = (byte)(e); /* [] indicates 8-bit at 32-bit shifted value: 0 000 0000 0000 0000 0000 0001 [1111 1100]
    0 * 2^0 + 0 * 2^1 + 1 * 2^2 + 1 * 2^3 + 1 * 2^4 + 1 * 2^5 + 1 * 2^6 - 1 * 2^7 = 
    0 * 1   + 0 * 2   + 1 * 4   + 1 * 8   + 1 * 16  + 1 * 32  + 1 * 64  - 1 * 128 = 
    0       + 0       + 4       + 8       + 16      + 32      + 64      - 128     = -4
*/

int g = (byte)(e);

    }
}

both byte 'f' and int 'g' works perfect but the book I'm reading now advice me to use int with a similar conditions without any explanations so the real thing I worry about is 'memory allocation'. Does it really matter which type to use or once byte value is shifted and the memory got expended to 32-bit it's impossible to reduce it back to 8-bit?

Additionally I've a strange question. How can I check the real 'bitness' of any value? Let's say when I execute something like this:

byte a = 10;
System.out.println(Integer.toBinaryString(a));
int b = 10;
System.out.println(Integer.toBinaryString(b));

The result is '1010' in both cases. But if I get it right byte 'a' use 8 bits of memory and int 'b' use 32. But for:

byte c = 5 << 1;
System.out.println(Integer.toBinaryString(c));

Result is '1010' too but now it use 32 bits of memory while byte and short values are promoted to int when an expression is evaluated. How can I 'see' this in real and ensure by myself?

Mike
  • 1,979
  • 2
  • 16
  • 29

1 Answers1

1

I'm not entirely sure what you are trying to do, but as for the assignment to f and g, both give the same result, since you assign to it (byte) e which fits within a byte variable.

If you would assign without casting, you'll get a diferent result, since the value of e is too large to fit within a byte.

As for the results of toBinaryString, they obviously don't show leading zeroes, which is why you see the same result for a byte variable and an int variable holding the same value. If you want to see all the bits, you'll have to print the leading zeroes yourself, and the number of leading zeroes depend on the type of the variable (so, for a byte variable, you'll have to add leading zeroes to reach a total of 8 bits, for int you'll have to reach 32 bits, etc...).

If you want to see the leading zeroes, you can make you own version of toBinaryString. Looking at an implementation of Integer, I found that toBinaryString calls toUnsignedString :

 public static String toBinaryString(int i) {
     return toUnsignedString(i, 1);
 }

 private static String toUnsignedString(int i, int shift) {
     char[] buf = new char[32];
     int charPos = 32;
     int radix = 1 << shift;
     int mask = radix - 1;
     do {
         buf[--charPos] = digits[i & mask];
         i >>>= shift;
     } while (i != 0);
     return new String(buf, charPos, (32 - charPos));
 }

As you can see, this method returns only part of the 32 chars that represent the binary value of the int. If you return new String(buf) instead, you'll get the full binary String with leading zeroes.

Eran
  • 387,369
  • 54
  • 702
  • 768
  • Sorry for my English, I need to discover how much bits used after casting. How much bits is int g = (byte)(e) 8 or 32? How to check this and if it's 32 how to force it to use 8 bits as a normal byte do? I want Java automatically print leading zeros depending of the type the current value is. Just for education purposes. – Mike Aug 23 '14 at 20:01
  • 1
    @Mike It's 32 since an int always occupies 32 bits, even if only the lowest 8 bits are non zero. If you want it to use only 8 bits, assign it to a byte variable. – Eran Aug 23 '14 at 20:03
  • Thank you, your code is a bit complicated for me now but I find it useful so I will try to test it multiple times. :) I also found question about sizeOf alternative in Java. I think that was exactly what I expect to see, but unfortunately it's not possible. http://stackoverflow.com/questions/2370288/is-there-any-sizeof-like-method-in-java Sad.. – Mike Aug 23 '14 at 20:22
  • Please tell me am I right that byte f = (byte)(e); will use 8 bits, but int e = d << 2; and int g = (byte)(e); will use 32 bits? And there is no way to check it or print using something like .currentAmountOfBits(f); (just for example)? – Mike Aug 24 '14 at 09:58
  • @Mike You are right, and there's nothing to check. That's what the spec of java says. byte is always 8 bits. int is always 32. – Eran Aug 24 '14 at 11:05