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.
Related
For this shifting:
System.out.println(0b10000000_00000000_00000000_00000001>>>32);
I'm getting this output value:
-2147483647
Is it correct?
The JLS says:
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.
Since 32 is 100000 in binary, only the five lowest bits are taken, which means you are not shifting the left-hand operand at all.
In other words, 0b10000000_00000000_00000000_00000001>>>32 is equivalent to 0b10000000_00000000_00000000_00000001>>>0.
Hence the result is 0b10000000_00000000_00000000_00000001.
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
Why if
int x = -1 // binary: 11111111111111111111111111111111
x = x >>> 31;
we have 00000000000000000000000000000001
but if
int x = -1
x = x >>> 32;
we have 11111111111111111111111111111111 (again -1)
but not 00000000000000000000000000000000 ?
From Section 15.19 of JLS:
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.
Emphasis mine. So:
x >>> n
is equivalent to:
x >>> n & 0x1f // or x >>> n % 32
So, x >>> 32 is equivalent to x >>> 32 & 0x1f <==> x >>> 0 == x.
So the Rule of Thumb is, whenever you shift a number by a multiple of 32(int is 32 bits), you get back the same value.
When applying the bit-shift operation only the lowest 5 bits of the right-hand operand are considered. Since 32 === 0 // mod 32, the result is no shifting.
Spent an entire day breaking my head over why a long l = i << 32 behaved strangely, then wrote some basic tests, had the WTF moment, and then chnged to long l = (long) i << 32 for it to work.
My only add to Rohit's answer is the reason why this is so. From IA-32 Intel Architecture Software Developer’s Manual 3:
The 8086 does not mask the shift count. However, all other IA-32 processors (starting with the Intel 286 processor) do mask the shift count to 5 bits, resulting in a maximum count of 31. This masking is done in all operating modes (including the virtual-8086 mode) to reduce the maximum execution time of the instructions
In RegularEnumSet implementation, there is a code:
elements = -1L >>> -universe.lengh
It uses a Long type integer to implement efficient EnumSet.
What is notable is that the right-hand operand of >>> is a negative figure.
I have tested and found that
int i = -1;
i >>> -3
has equivalent effect with
int i = 1;
i << 3;
So why bother to write in this ambiguous form?
From the "Java Language Specification", section 15.19, about shifting "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-and operand were subjected to a bitwise logical AND operator & with the mask value 0x3f. The shift distance actually used is therefore awlays 0 to 64, inclusive."
So, >>> -3 has equivalent effect as >>> 61, and -1L >>> -n equals -1L >>> (0x3f&-n)
Actually this seems to be the most effective way of producing a consecutive 1s in the lowest n-bits of a long integer.
First, note that the code you quoted uses -1L, not -1. Longs are unsigned, so -1L is equivalent to setting all the bits on the long, or getting the highest possible long number.
>>> -3 has equivalent effect with << 3
It doesn't. The unsigned right shift operator (>>>) shifts zeroes into the sign bit, while >> and << preserve the sign of the value being shifted, shifting 1 or 0 accordingly. That's why -1L >>> -3 is 7 (0111b) and 1L << 3 is 8 (1000b).
In the Core Java Volume1 book there is a caution that say:
CAUTION: The right-hand side argument of the shift operators is reduced modulo 32
(unless the left-hand side is a long, in which case the right-hand side is reduced modulo 64).
For example, the value of 1 << 35 is the same as 1 << 3 or 8.
What exactly does this mean? also why 1 become 8, instead of being 0 after 35 left shifting?
many thanks
Reduced modulo 32 means (at its base level) you keep subtracting 32 until you have a number between 0 and 31 inclusive.
In other words:
actualValue = givenValue % 32;
The reason it does this is because it makes little sense to shift a 32-bit value 32 bits to the left (or right) since it will always be zero (because you're shifting bits out on one side and shifting zeros in on the other side - doing that 32 times to a 32-bit value is going to result in zero no matter what you started with).
So for Java integers (32-bit), 31 is the sensible limit. For longs (64-bit), 63 is the sensible limit.
In the example you give, 1 << 35 has the shift value reduced from 35 to 3 (since 35 % 32 == 3) and 1 << 3 is 8:
Binary
0000 0001 (1 << 0) == 1
0000 0010 (1 << 1) == 2
0000 0100 (1 << 2) == 4
0000 1000 (1 << 3) == 8
||||
|||+--- 1
||+---- 2
|+----- 4
+------ 8
In many programming languages, shifting by more than the size of a numeric data type (32 bits for an int, 64 bits for a long) is undefined. On the other hand, Java defines it such that (n << d) is equivalent to (n << (d % 32)) where n is an int, and (n << d) is equivalent to (n << (d % 64)) where n is a long.
So, 1 << 35 is equivalent to 1 << (35 % 32), which equals 1 << 3 = 8.
More succinctly
a << b
is the same as
a << (b & 31)
for int types.
The difference is that -1 % 32 is -1 whereas -1 & 31 is 31 and 1 << -1 == 0x80000000
This behaviour is defined in JLS 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.
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.