Bitwise operation && overflow [duplicate] - java

This question already has answers here:
How do shift operators work in Java? [duplicate]
(9 answers)
Why in Java right-shifting 16 by 32 results in 16 and not 0? 16>>32 = 16 Why? [duplicate]
(1 answer)
Closed 2 years ago.
Why the results of this two lines are different in java?
int a = 1;
System.out.println(a << 32); //output: 1
System.out.println(a << 31 << 1); //output: 0

Per JLS 8 § 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
When shifting an int the shift distance is thus effectively the value of the right operand mod 32 (at least when the right operand is non-negative). So a << 32 is basically the same as a << 0, i.e., just a. But a << 31 << 1 first shifts a, whose value is 0x00000001, left by 31 to yield 0x80000000, which is then shifted left by 1 to yield 0x00000000.

Related

Understanding unsigned right shift

The JLS 15.19 describes the formula for >>> operator.
The value of n >>> s is n right-shifted s bit positions with
zero-extension, where:
If n is positive, then the result is the same as that of n >> s.
If n is negative and the type of the left-hand operand is int, then
the result is equal to that of the expression (n >> s) + (2 << ~s).
If n is negative and the type of the left-hand operand is long, then
the result is equal to that of the expression (n >> s) + (2L << ~s).
Why does n >>> s = (n >> s) + (2 << ~s), where ~s = 31 - s for int and ~s = 63 - s for long?
If n is negative it means that the sign bit is set.
>>> s means shift s places to the right introducing zeros into the vacated slots.
>> s means shift s places to the right introducing copies of the sign bit into the vacated slots.
E.g.
10111110000011111000001111100000 >>> 3 == 00010111110000011111000001111100
10111110000011111000001111100000 >> 3 == 11110111110000011111000001111100
Obviously if n is not negative, n >> s and n >>> s are the same. If n is negative, the difference will consist of s ones at the left followed by all zeros.
In other words:
(n >>> s) + X == n >> s (*)
where X consists of s ones followed by 32 - s zeros.
Because there are 32 - s zeros in X, the right-most one in X occurs in the position of the one in 1 << (32 - s), which is equal to 2 << (31 - s), which is the same as 2 << ~s (because ~s == -1 - s and shift amounts work modulo 32 for ints).
Now what happens when you add 2 << ~s to X? You get zero! Let's demonstrate this in the case s == 7. Notice that the the carry disappears off the left.
11111110000000000000000000000000
+ 00000010000000000000000000000000
________________________________
00000000000000000000000000000000
It follows that -X == 2 << ~s. Therefore adding -X to both sides of (*) we get
n >>> s == (n >> s) + (2 << ~s)
For long it's exactly the same, except that shift amounts are done modulo 64, because longs have 64 bits.
Here is some additional context that will help you understand pbabcdefp's answer if you don't already know the basics he assumes:
To understand bitwise operators you must think about numbers as strings of binary digits, eg. 20 = 00010100 and -4 = 11111100 (For the sake of clarity and not having to write so many digits I will be writing all binary numbers as bytes; ints are the same but four times as long). If you are unfamiliar with binary and binary operations, you can read more here. Note how the first digit is special: It makes numbers negative, as if it had a place value (remember elementary math, the ones/tens/hundreds places?) of the most negative number possible, so Byte.MIN_VALUE = -128 = 1000000, and setting any other bit to 1 always increases the number. To easily read a negative number such as 11110011, know that -1 = 11111111, then read the 0s as if they were 1s in a positive number, then that number is how far away you are from -1. So 11110011 = -1 - 00001100 = -1 - 12 = -13.
Also understand that ~s is bitwise NOT: It takes all the digits and flips them, this is actually equivalent to ~s = -1 - s. Eg ~5 (00000101) is -6 (11111010). Observe how my suggested method for reading negative binary numbers is simply a trick to be able to read the bitwise NOT of the number rather than the number itself, which is easier for negative numbers close to zero because those numbers have fewer 0s than 1s.

Bitwise shift to get max unsigned value

I need to generate max value for unsigned 64 bit long in java, using bitwise shift. So here is my function:
public static final boolean isMaxLimitMiss(int bitsCount, BigDecimal value, int signum) {
if (signum == 0) {
BigDecimal val = new BigDecimal(Long.valueOf((1 << (bitsCount)) - 1));
return Long.compareUnsigned(value.longValue(), val.longValue()) > 0 ? true : false;
}
return value.compareTo(new BigDecimal((1L << (bitsCount - 1)) - 1)) > 0 ? true : false;
}
It just checks that value is in range for max value that bitsCount provides.
It works fine for signed data.
In case 64 bit, and for unsigned (Yes, there are no unsigned long in java. I trying to simulate it) - it is incorrect. ((1 << (bitsCount)) - 1 evaluates to 0
How can I pass value = 2^64 - 1 into BigDecimal constructor?
One first thing:
(1 << (bitsCount)) - 1
This is a mistake because you are only performing integer arithmetic. You needed:
(1L << (bitsCount)) - 1
But anyway I assume bitsCount is 64. In Java you cannot shift by a number larger than 63 for a long and 31 for an int (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.
This is why you get 0, because the expression is reduced to (1 << 0) - 1.
You need to compute your max value a different way, for example:
-1L >>> (64 - bitsCount)
or:
BigInteger.ONE.shiftLeft(bitsCount).subtract(BigInteger.ONE)
If you are testing a BigDecimal it would be safer to not use long at all here.

Why in Java right-shifting 16 by 32 results in 16 and not 0? 16>>32 = 16 Why? [duplicate]

This question already has answers here:
How do shift operators work in Java? [duplicate]
(9 answers)
Closed 8 years ago.
I came across a weird looking situation while using right-shift operator in java. When I right-shift 16 by 31 it results in 0 however on trying to right-shifting 16 by 32 it remains 16 itself. Could someone please explain it as I am going crazy over it.
public class RightShiftTest {
public static void main(String args[]) {
int b = 16;
System.out.println("Bit pattern for int " + b + " is " +Integer.toBinaryString(b));
// As expected it is 0
System.out.println("After right-shifting " + b + " for 31 times the value is " + (b>>31) + " and bit pattern is " +Integer.toBinaryString(b>>31));
// But why is it not 0 but 16
System.out.println("After right-shifting " + b + " for 32 times the value is " + (b>>32) + " and bit pattern is " +Integer.toBinaryString(b>>32));
}
}
Output:
Bit pattern for int 16 is 10000
After right-shifting 16 for 31 times the value is 0 and bit pattern is 0
After right-shifting 16 for 32 times the value is 16 and bit pattern is 10000
The Java Language Specification states
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.
The value 32 is represented as
100000
the lowest 5 bits are 00000 so 0, shifted by 0 bits.

What does this mean (<< and >>> in calculation)? [duplicate]

This question already has answers here:
why is 1>>32 == 1?
(2 answers)
Closed 8 years ago.
I found this integer variable declaration in a Java class:
int i7 = ((0x1F & arrayOfByte[i][4]) << 9) + ((0xFF & arrayOfByte[i][5]) << 1) + (0x1 & (0xFF & arrayOfByte[i][6]) >>> 7);
But are the arrows (>>> and <<) mean/doing?
Kind regards,
Bastiaan
UPDATE:
Sow they are bitshift operators, thanks!
Found this good explanation video: https://www.youtube.com/watch?v=1qa0zvcdHXI
Throughout this post let's assume numbers are one hex digit, just for simplicity.
">>" is the bit shift operator. For example:
8 >> 1 == 8 / 2 == 4;
Which in binary is equivalent to
b1000 >> 1 == b0100;
Adding the third ">" into the operator inserts a 0 into the now far left slot, instead of doing sign extension to determine it's value.
-1 >> 1 = b1111
-1 >>> 1 = b0111
This is more useful for things like bit masks, where forcing the new value to 0 is convenient. And is only applicable to right shifting, there is no <<< operator.

bit shift operation does not return expected result

Why does Java return -2147483648 when I bit shift 1 << 63 ?
The expected result is 9 223 372 036 854 775 808, tested with Wolfram Alpha and my calculator.
I tested:
System.out.print((long)(1 << (63)));
There's an important thing to note about the line
System.out.print((long)(1 << (63)));
You first take (1 << 63), and then you cast to long. As a result, you are actually left-shifting in integers, so the long cast doesn't have any effect. That's why shifting 63 bits left gives the min integer rather than the min long.
But there's another, more important point. Java longs are always signed, so even the line
System.out.print(1L << 63);
would give a negative number. Under two's complement, whenever the leftmost bit is a 1 the number is negative.
You actually cannot represent the number 263 = 9223372036854775808 in a Java primitive type, because that number is bigger than the maximum long, and long is the largest primitive type. You can represent this number as a BigInteger, though. You can even generate it via a left-shift by 63 with the code
BigInteger.ONE.shiftLeft(63)
You are having an integer overflow [twice].
1 << 32 == 1
1 << 31 == -2147483648 [ becuase this is the binary representation in 2's complement for -2147483648]
1 << 63 == 1 << (32 + 31) == (1 << 32) << 31 == 1 << 31 == -2147483648
When you do (long)(1 << (63)) you are only casting the result of 1 << (63) [which is -2147483648] to a long - and it does not change its value.

Categories