I think understand what they fundamentally do - operate on bits (flip, shift, invert, etc...).
My issue is that I don't know when I'd ever need to use them, and I don't think I fully understand bits.
I know that there are 8 bits in a byte and I know that bits are either a 0 or 1. Now here is where I start to get confused... I believe data types define combinations of bits differently. So if I declare an int, 32 bits are set aside for numbers, if I declare a char, 8 bits are set aside and the bits for that data type define a letter.
Running with that idea, I did the following basic operation in java which confuses me:
int num = 00000010;
System.out.println(num);
This prints 8 and if I define num this way:
int num = 00000100;
System.out.println(num);
This prints 64
So to practice with bitwise operations (just for the hell of it) I tried this:
int num = 00000010 << 1;
System.out.println(num);
And it prints 16 where as I thought it would shift the bits by one to the left and print 64.
What is happening here, and when would I ever need to apply this method of manipulating bits?
You are accidentally specifying an octal literal when you specify a number with a leading zero.
00000010 => 1*8^1 + 0*8^0 => 8
00000100 => 1*8^2 + 0*8^1 + 0*8^0 => 64
The JLS, Section 3.10.1, describes octal and binary literals:
An octal numeral consists of an ASCII digit 0 followed by one or more
of the ASCII digits 0 through 7 interspersed with underscores, and can
represent a positive, zero, or negative integer.
A binary numeral consists of the leading ASCII characters 0b or 0B
followed by one or more of the ASCII digits 0 or 1 interspersed with
underscores, and can represent a positive, zero, or negative integer.
You are bit-shifting your 8 by one to the left, effectively multiplying it by 2 to get 16. In bits:
00000100 => 00001000
(8 => 16)
Binary literals are expressed with leading 0b, e.g.:
0b000010 => 2
Related
I'm not asking for a built-in class that accomplishes this, I'm just curious on how encoding works behind the scenes in java. For example, An integer in java can be stored in 4 bytes, between -2147483648 and 2147483647. Lets use 500 as the number for this demonstration. From what I understand, the computer initially stores this number in memory as 1F4 in hex, which is 00000000 00000000 00000001 11110100 in binary. When I looked up how ASCII works, it encodes each digit 0-9 to its corresponding ASCII value (0 translates to 048). However, how is the binary number stored in ram able to separate each digit so that each digit can be encoded to its corresponding ASCII value? We know that the number is 500, but this is just an abstraction. The computer just sees 1's and 0's. So how is the 5 mapped to 053, and both 0's mapped to 048 for this example. Does the jvm account for this automatically behind the scenes? Or am I misunderstanding how the entire process works. Thanks.
Well, IF I understand your question directly...
You could start by dividing your integer by 10 and getting the remainder -- the mod function in Java (%) is useful for this.
int digitInteger = originalNumber % 10;
The digitInteger variable now holds a number 0-9, the integer version of the ASCII (or Unicode, or whatever) of the last digit in the number. Unfortunately for your example, this will be a fairly boring 0.
Let us instead use the number 543 as our example, it will make things easier. If originalNumber was 543, then digitInteger will now be 3. Since 48 represents ASCII 0, then you can add that to digitInteger to get the ASCII equivalent. I'll leave it to you put that somewhere, since Java does not deal with ASCII as its default encoding. (Unicode, I believe, has the same values as ASCII for these digits).
Now you execute something like
originalNumber = originalNumber / 10;
This integer division will truncate the digit you just isolated, 3 in our case, and originalNumber is now 54.
You repeat this process - mod by 10 to isolate the last digit, convert to character, prepend to characters previously found, integer divide by 10 to truncate the last digit -- until originalNumber is 0 -- digitInteger, as you can probably see now, will be 4 on the next round and 5 on the round after that, and you prepend those to the 3 you got the first time to get your ASCII equivalent.
I've been getting a weird problem with Java, and have tested on both a Windows and Mac system and have this problem come up consistently.
Take a look at this code
int a = -32; //11100000 as per two's complement
System.out.println(a >>> 2);
I expect this code to produce 56, which is 00111000 in its binary form. However, it produces the value 1073741816, 111111111111111111111111111000 in its binary form. I understand ints are 32-bits in java, but setting the type of byte also does the same thing.
However if I declare a binary literal like this
int b = 0b11100000;
System.out.println(b);
System.out.println(b >>> 2);
The first statement produces the value 224 (expected -32), while the second statement produces the expected value of 56
Am I going insane?
Your bit pattern in b is not 11100000 like you say, but 11111111 11111111 11111111 11100000
You're using an int which is 32 bits - not a byte - and using binary literals doesn't change that.
Even if you used byte rather than int it wouldn't fix your problem, because the Java bitshift operators first promote any type less than 32 bits to 32 bits.
So the resulting bit pattern is 00111111 11111111 11111111 11111000 after the shift.
If you want to mimic working with an 8-bit value, you need to bit-mask the 32-bit value to the lower 8 bits before applying the bitshift (you may as well use >> rather than >>> now)
System.out.println((b & 0xff) >>> 2);
I'm reading Core Java by Horstmann.
This is an example:
byte nx = (byte)300;
System.out.println(nx);
The result is 44. I can't understand why? I suppose 2 variants: 1) everything is ruined and you just get a complete garbage; 2) there is some logic.
I'm inclined to the second variant as the book tells me that it is 44 that is received. So, there is some algorithm behind it.
Could you help me understand.
A cast to byte will only retain the least significant 8 bits. 300 (as an int here) in binary is
00000000 00000000 00000001 00101100
Retaining the last 8 bits throws away the most signficant 1 (and everything else before it) which represents 256, so the remaining value is 300 - 256 = 44
00101100
The byte data type is only 8 bits long, and the decimal number 300 requires 9 bits.
When you cast it, you truncated it and cut off the leftmost bit, leaving the binary representation of the decimal number 44.
If you need an analogy, think of casting from a float like 35.6 to an int. Because ints cannot have decimal places, that cast truncates '.6' off of the float, ignoring it completely in the returned value.
Look at the binary expansion of 300:
100101100
Now chop off all but the last 8 bits (the width of a byte in Java):
00101100
Now convert that back to an integer value:
44
Note that you have to be careful about sign bits. You can't just take the remainder after dividing by 256. For instance:
byte nx = (byte)400;
System.out.println(nx);
will print -112 (not 144). That's because the bit pattern after the cast is
10010000
and the left-most (eighth) bit is treated as the sign bit in the two's complement representation of -112.
How is it that System.out.println(052) and System.out.println(0x2a) both print 42?
Does this have to do with binary at all?
052 is an octal (base 8) literal.
0x2a is a hexadecimal (base 16) literal.
System.out.println(0x2a) uses a hex literal (0x prefix indicates this), which has a decimal equivalent of 42.
System.out.println(052) uses an octal literal (leading 0 indicates this), which has a decimal equivalent is 42.
System.out.println will print the integers according to their decimal representation. If you want to keep hex, try System.out.printf("%x\n", 0x2a), or, for octal, "%o" in place of "%x".
052, 0x2a and 42 are all different ways of writing the (decimal, base 10) number 42:
052 is octal, or base 8
0x2a is hexadecimal, or base 16
42 is the familiar decimal, base 10
java allows you to use numbers literally in your code using any of these different formats: using a leading 0x to specify hexadecimal, or a leading zero, 0 to specify octal.
This has to do with binary inasmuch as anything that you'll do with java has to do with binary.
By the way, the binary, base 2 representation of 42 is: 101010. You can also use binary literals in java by preceding them with 0b, so 0b101010 == 0x2a.
052, starts with 0, so it's an octal number and hence 8*5+2=42
0x2a starts with 0x, so it's a hexadecimal number and hence 16*2+a = 32 + 10=42
052 is an octal literal, and is equivalent to 0 * 8^2 + 5 * 8^1 + 2 * 8^0.
0x2a is a hexadecimal literal, equivalent to 2 * 16^1 + 10 * 16^0.
5 * 8 + 2 and 2 * 16 + 10 can be seen to be equivalent, as 5 * 8 is equivalent to 4 * 8 + 8, and 8 + 2 equals 10.
This question already has answers here:
Difference between >>> and >>
(9 answers)
Closed 5 years ago.
If the shifted number is positive >>> and >> work the same.
If the shifted number is negative >>> fills the most significant bits with 1s whereas >> operation shifts filling the MSBs with 0.
Is my understanding correct?
If the negative numbers are stored with the MSB set to 1 and not the 2s complement way that Java uses the the operators would behave entirely differently, correct?
The way negative numbers are represented is called 2's complement. To demonstrate how this works, take -12 as an example. 12, in binary, is 00001100 (assume integers are 8 bits though in reality they are much bigger). Take the 2's complement by simply inverting every bit, and you get 11110011. Then, simply add 1 to get 11110100. Notice that if you apply the same steps again, you get positive 12 back.
The >>> shifts in zero no matter what, so 12 >>> 1 should give you 00000110, which is 6, and (-12) >>> 1 should give you 01111010, which is 122. If you actually try this in Java, you'll get a much bigger number since Java ints are actually much bigger than 8 bits.
The >> shifts in a bit identical to the highest bit, so that positive numbers stay positive and negative numbers stay negative. 12 >> 1 is 00000110 (still 6) and (-12) >> 1 would be 11111010 which is negative 6.
Definition of the >>> operator in the Java Language Specification:
The value of n>>>s is n right-shifted s bit positions with zero-extension. If n is positive, then the result is the same as that of n>>s; if n is negative, the result is equal to that of the expression (n>>s)+(2<<~s) if the type of the left-hand operand is int, and to the result of the expression (n>>s)+(2L<<~s) if the type of the left-hand operand is long.
Just the opposite, the >>> fills with zeros while >> fills with ones if the h.o bit is 1.