unsigned right shift by negative number in Java [duplicate] - java

This question already has answers here:
Negative logical shift
(2 answers)
Closed 7 years ago.
I am having a difficult time wrapping my head around negative unsigned bitwise operators.
For example, I have the code below. It prints out the value 7 and I don't understand why.
int num1 = -37, num2 = -3;
System.out.println( num1 >>> num2);
// Essentially the same as System.out.println( -37 >>> -3);
// I just wanted to emphasize that i am working with Integers
From my knowledge, the number -37 in binary format is as shown below.
11111111 11111111 11111111 11011010 = -37 (in decimal format)
If we are unsigned right shift of 3 ( -37 >>> 3, not -37 >>> -3), from my knowledge (please correct me if my theory is flawed or lacking key concepts), it shifts the bytes to the right by 3 and the 3 bits that fall out on the right most position appear on the left most position in a flipped down state (from zero to one), meaning that we get the following result.
00011111 11111111 11111111 11111011 = 536870907 (in decimal format).
However, if we apply an unsigned right shift of -3 ( -37 >>> -3), we get the result 7. I don't understand why it is returning 7. Could somebody please explain it to me?

It seems counter-intuitive, but when shifting an int, only the last 5 bits of the shift amount are used, according to the JLS, Section 15.19.
If the promoted type of the left-hand operand is int, then only the five lowest-order bits of the right-hand operand are used as the shift distance. It is as if the right-hand operand were subjected to a bitwise logical AND operator & (§15.22.1) with the mask value 0x1f (0b11111). The shift distance actually used is therefore always in the range 0 to 31, inclusive.
This means that -3 only has the last 5 bits used, or 29. Here's -3 in bits to show what's going on:
11111111 11111111 11111111 11111101
The last 5 bits are 11101, or 29 in decimal.
The right-shift distance is 29, which means that the first 3 bits are kept and shifted all the way to the right. Taking -37:
11111111 11111111 11111111 11011010
After the unsigned shift of 29 places, 7 is left:
00000000 00000000 00000000 00000111
As you can see, a negative shift amount is confusing at best. Try to avoid it and always attempt to use an actual number between 0 and 31 for the shift amount for shifting ints.

Related

Java pipe & ampersand with integers [duplicate]

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

Is java bit shifting circular?

I have this behavior using Java:
int b=16;
System.out.println(b<<30);
System.out.println(b<<31);
System.out.println(b<<32);
System.out.println(b<<33);
output:
0
0
16
32
Is java bit shift circular? IF not, why I get 0 when b<<30 and 16 when b<<32?
Bit shifting is not circular; for bit-shifting ints, Java only uses the 5 least-significant bits, so that (b << 0) is equivalent to (b << 32) (is equivalent to (b << 64), etc.). You can simply take the bit-shifting amount and take the remainder when dividing by 32.
Something similar occurs for bit-shifting longs, where Java only uses the 6 least-significant bits, so that (aLong << 0) is equivalent to (aLong << 64).
Section 15.19 of the JLS talks about this:
If the promoted type of the left-hand operand is int, only the five lowest-order bits of the right-hand operand are used as the shift distance. It is as if the right-hand operand were subjected to a bitwise logical AND operator & (§15.22.1) with the mask value 0x1f (0b11111). The shift distance actually used is therefore always in the range 0 to 31, inclusive.
If the promoted type of the left-hand operand is long, then only the six lowest-order bits of the right-hand operand are used as the shift distance. It is as if the right-hand operand were subjected to a bitwise logical AND operator & (§15.22.1) with the mask value 0x3f (0b111111). The shift distance actually used is therefore always in the range 0 to 63, inclusive.
(emphasis mine)
(You can't bit-shift floats or doubles, and attempting to bit-shift a short or a byte would be subject the value to unary numeric promotion to an int anyway.)
You get 0 from 16 << 30, because the 1-bit from 16
00000000 00000000 00000000 00010000
gets shifted off the end of the int and gets discarded.
// Discarded - Result-----------------------------
(00000100) 00000000 00000000 00000000 00000000
No, it's not circular shift. It's normal left-shift. It's just that, for int type left side operand, Java uses just 5 lower order bits of the right operand for shifting. This is as per JLS §15.9:
If the promoted type of the left-hand operand is int, only the five
lowest-order bits of the right-hand operand are used as the shift
distance. It is as if the right-hand operand were subjected to a
bitwise logical AND operator & (§15.22.1) with the mask value 0x1f
(0b11111). The shift distance actually used is therefore always in the
range 0 to 31, inclusive
So, for 16 << 32, considering only 5 lower order bits of 32, the expression is equivalent to:
16 << 32 & 0x1f
which is equal to 16.

Shifting by Negative Numbers

I am pretty confused with this expression here. I am a Java programmer but I am not very well versed with bit manipulation.
I think I understand the below correctly:
Input : 1 << 10
Output: 0000000000000000000010000000000
For positive numbers, I think it is you move 1 by 10 bits.
The confusion is when I have the below:
int val = -10 (binary representation : 1111111111111111111111111110110 )
Input : 1 << val
Output: 0000000010000000000000000000000
That would be really great if someone can explain me the meaning of left shifting or right shifting by negative number.
<< (and other shift operators) only takes 5 least significant bits of its right operand for int, and 6 for long, because it makes no sense to shift int by more than 31.
In your case it's 0b10110 = 22.
Therefore 1 << (-10) is equivalent to 1 << 22.
From the JLS, section 15.19:
If the promoted type of the left-hand operand is int, only the five lowest-order bits of the right-hand operand are used as the shift distance. It is as if the right-hand operand were subjected to a bitwise logical AND operator & (§15.22.1) with the mask value 0x1f (0b11111). The shift distance actually used is therefore always in the range 0 to 31, inclusive.
In other words,
1 << -10
is equivalent to:
1 << (-10 & 0x1f)
... which is
1 << 22

System.out.println(16 >>> 3)? [duplicate]

This question already has answers here:
Difference between >>> and >>
(9 answers)
Closed 9 years ago.
I try the code
System.out.println( 16 >>> 3);
and the output is 2 !
but how does this work? What is the syntax?
16 >> 3 is a bitshift to the right, and is equivalent to dividing by 8 (2 ** 3).
16 -> 00010000
^
\
\
2 -> 00000010
This is called right-shift with zero-fill (also called - unsigned right shift).
To make it easy to understand, for every shift, your number is divided by 2. So:
16 >>> 3 == 16 / 2^3 == 16 / 8 == 2
For more details see, JLS - Shift Operators.
For real visualization, take a look at the bit representation of the two numbers:
16 - 00010000
16 >>> 3 - 00000010 == 2
Another note, the 3 chevrons indicate an unsigned right bit shift. Although it does not make a difference in this example...
The extra > indicates the sign is not reserved, an example:
-128 >> 2 = -128 / 2^2 = -32
The signed bit is retained giving:
(1) 10000000 >> 2 = (1) 100000
11111111 11111111 11111111 10000000 >> 2 = 1111111 11111111 11111111 11100000
If >>> is used then the signed bit is also shifted converting it to a positive number.
-128 >>> 2 = 536870896
11111111 11111111 11111111 10000000 >> 2 = 0011111 11111111 11111111 11100000
The >>> operator is performing an unsigned right-shift of bits, when applied to an integer it has the effect of dividing by two. In particular, if the integer is a power of two, each right-shift exactly halves the value. For example:
16 >>> 1 // returns 8
16 >>> 2 // returns 4
16 >>> 3 // returns 2
In binary form, 16 is represented as 10000. If we shift the value three times to the right it ends up as 00010, which is 2. Also, take a look at the Java tutorial.
16 in binary is 00010000. You are shifting the bits right three positions which results in 00000010 which is 2
This is a bit shift, which is dividing by 2^3 (due to shifting by 3 positions) and truncating(rounding down) as we are not doing fillaround.
When using >>> we move to the right and divide.
When using <<< it goes opposite, so you'd multiply by the correct power of 2.
Bit shifts are a type of bitwise operation that operates on a primitive(almost always number's) bits directly.
It's an unsigned right shift operator, and the above shifts 3 times.
i.e. it divides by 2 each time, giving you 2.
See here for more information on Java operators.
You're using a bitwise shift consult this post
In binary, every 0 is an increasing magnitude of the power 2 for example:
10000 = 16
01000 = 8
00100 = 4
00010 = 2
00001 = 1
The expression 16 >>> 3 in java is saying to move the bit over 3 places, so we are left with 2.

Difference between >> and >>> operators in Java [duplicate]

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.

Categories