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.
Related
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.
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
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.
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).