Operand1 ShiftOperator Operand2
Shift Rule
If either of the Operand is Negative don't forget to calculate its 2's complement since Negative integers is stored in Memory using 2's complement
Mask Operand2 with 0x1F
Right shift
81814621>>-12 = 78
81814621>>>-12 = 78
OK!!
Right shift (Operand1 is NEGATIVE)
-81814621>>-12 = -79
-81814621>>>-12 = 4017
Why different?
Left shift
21<<-12 = 22020096
-21<<-12 = -22020096
Unlike Right shift no matter Operand1 is Positive/Negative
only sign get changed instead value
Thanks for all of your support! now i have a better idea on it...:)
Wherever you got that from, it's wrong. Operand2 cannot possibly be either negative or have anything at all in its leftmost five bits after masking it with 0x1F. There is nothing in the Java Language Specification about taking the twos-complement of the shift distance, or using its left-most five bits. Read what it really says. Don't rely on arbitrary sources, or just make it up.
EDIT -81814621 is 0xFFFFFFFFFB1F9BA3, -12 is 0xFFFFFFFFFFFFFFF4, bottom five bits of that is 0x14 or 20, right shift the first operand by 20 gives 0xFFFFFFFFFFFFFFB1, which is -79.
The "rule" about what to do with the right-hand side operator of the shift is there because the list of values of the right operand that truly make sense is very short: for ints the range is from zero to 31, inclusive; for longs, it is zero to 63.
All other values of int on the right-hand side need to be converted to a value in the specified range. The "rule" spells out the process - i.e. re-interpreting the number as positive (that's what the two's complement is about), then masking off the higher bits, keeping the last five.
In contrast, the left operand can retain its full range. The only difference that you are experiencing has to do with the difference between >> and >>>, that is, between an operator that interprets the left-hand side operand as signed for shifting, and the one that interprets it as unsigned.
The purpose behind the >>> operator is explained in this answer. In your example, when you right-shift a negative number with the two operators, the >> leaves the number negative by sigh-extending it (i.e. shifting ones on the left) while >>> makes it positive by shifting in zeros.
Related
I have the following value:
int x = -51232;
Java integers are 32 bits, so in binary this should be the following:
10000000000000001100100000100000
The sign bit on the left is set to 1 since x is negative.
Then I do the operation
x = (x & Integer.MAX_VALUE);
Integer.MAX_VALUE is 2147483647 and in binary that would be:
01111111111111111111111111111111
0 on the left because the value is positive.
So why does x & Integer.MAX_VALUE yield 2147432416? The AND operator should only retrieve bits that x and Integer.MAX_VALUE have in common, which should be equivalent to -x (since they do not share the same sign bit).
What's going on here?
Your misunderstanding is caused by lack of knowledge regarding how negative integers are represented in binary in Java. You should read about 2's complement.
10000000000000001100100000100000 is not the binary representation of -51232.
11111111111111110011011111100000 is.
And when you run bitwise AND, you get:
11111111111111110011011111100000 (-51232)
01111111111111111111111111111111 (Integer.MAX_VALUE)
--------------------------------
01111111111111110011011111100000 (2147432416)
Here's the binary representation of -51232 next to the binary representation of 51232. You can see that their sum is 232. that's always the case with 2's complement, for any pair of ints x and -x.
00000000000000001100100000100000 (-51232)
11111111111111110011011111100000 (51232)
Integers are stored in two complement: https://en.m.wikipedia.org/wiki/Two%27s_complement.
Thus while the leftmost bit indicate negative numbers, it is not really a sign bit as it would be for floating point numbers in common representation.
The main reason of this representation is that it make it easy to do addition and substraction among other at the hardware level.
One should not that with two complement notation, -1 is represented by all bit set to 1.
I'm reading Java spec. and here is written:
The value of n >> s is n right-shifted s bit positions with
sign-extension. The resulting value is floor(n / 2s). For non-negative
values of n, this is equivalent to truncating integer division, as
computed by the integer division operator /, by two to the power s.
So if I have the following:
27 >> 3 // 00011011 >> 3 = 00000011 = 3 = 27/8
the result is 3; in fact 27/8 = 3.375 and thus 3 is that value truncated.
But the spec say nothing when left operand is negative.
So if I have the following:
-50 >> 2 // 11001110 >> 2 = 11110011 = -13 != -50/4
the result is -13; but -50/4 = -12.5 and thus -13 is not that value truncated.
So what's the rounding system Java use when the left operand is a negative value?
Maybe ceil(n / 2s)?
The resulting value is floor(n / 2s).
Floor means round down: round towards negative infinity. This is not the same as truncation, i.e. removing the fractional part. Truncation would cause positive numbers to round down and negative numbers to round up.
The floor of -12.5 is -13.
Demo.
Generally speaking Java does not use a rounding system at all, it just shifts some bits. If you need floor or ceil then use floor or ceil and use bit-shift operators when you need them.
I have the following piece of code:
int SOME_MASK = 0x0000ffff;
int value = /* some value */;
int something = SOME_MASK & value;
// WHY IS "something" guaranteed to be non-negative ?
if (something != NEGATIVE_CONSTANT) {
// do something here....
}
I keep getting the FindBugs analysis warning:
Correctness - Bad comparison of nonnegative value with negative
constant This code compares a value that is guaranteed to be
non-negative with a negative constant.
The warning pops up for the line where comparing the bitwise AND result with the negative constant.
I am not sure why a Bitwise AND result is guaranteed to be non-negative? is this always the case?
When SOME_MASK starts with a '0' bit, the result of SOME_MASK & value must be positive.
The result of bitwise-AND can be negative, e.g. (-1) & (-1) is definitely -1.
However, if either operand is nonnegative, the result must also be nonnegative. This is because in 2's complement representation, a negative number must have its 31st bit set, and a nonnegative number must have its 31st bit cleared. Since & will set a bit only if both operand's bit is set, the result is negative if and only if both inputs are negative.
Since SOME_MASK = 0xffff is positive, the result of SOME_MASK & value will never be negative.
something is guaranteed not to be negative because Java's signed int type uses the most significant bit for sign, and that bit is cleared (0) in SOME_MASK. Since something is the result of something being ANDed with that mask, it can't have that bit set, so it can't be negative.
Can the result of a bitwise AND operator be negative (in Java)
In general - Yes.
In the case of your example - No.
In Java, integers are represented in two's complement signed binary representation. One characteristic of this representation is that the most significant (i.e. left-most) bit is one for a negative number and zero for a positive number.
In your example, you are ANDing with 0x0000ffff, and that is setting the top 16 bits to zero. That means that the result of that expression cannot be a negative number.
By contrast, if you ANDed with 0xffff0000, the result could be negative.
The bitwise AND of two negative integers is always negative. The bitwise AND of two integers, where one or both are positive, is always positive. To see why, think about the binary representation, and what happens to the highest bit.
I understand what the unsigned right shift operator ">>>" in Java does, but why do we need it, and why do we not need a corresponding unsigned left shift operator?
The >>> operator lets you treat int and long as 32- and 64-bit unsigned integral types, which are missing from the Java language.
This is useful when you shift something that does not represent a numeric value. For example, you could represent a black and white bit map image using 32-bit ints, where each int encodes 32 pixels on the screen. If you need to scroll the image to the right, you would prefer the bits on the left of an int to become zeros, so that you could easily put the bits from the adjacent ints:
int shiftBy = 3;
int[] imageRow = ...
int shiftCarry = 0;
// The last shiftBy bits are set to 1, the remaining ones are zero
int mask = (1 << shiftBy)-1;
for (int i = 0 ; i != imageRow.length ; i++) {
// Cut out the shiftBits bits on the right
int nextCarry = imageRow & mask;
// Do the shift, and move in the carry into the freed upper bits
imageRow[i] = (imageRow[i] >>> shiftBy) | (carry << (32-shiftBy));
// Prepare the carry for the next iteration of the loop
carry = nextCarry;
}
The code above does not pay attention to the content of the upper three bits, because >>> operator makes them
There is no corresponding << operator because left-shift operations on signed and unsigned data types are identical.
>>> is also the safe and efficient way of finding the rounded mean of two (large) integers:
int mid = (low + high) >>> 1;
If integers high and low are close to the the largest machine integer, the above will be correct but
int mid = (low + high) / 2;
can get a wrong result because of overflow.
Here's an example use, fixing a bug in a naive binary search.
Basically this has to do with sign (numberic shifts) or unsigned shifts (normally pixel related stuff).
Since the left shift, doesn't deal with the sign bit anyhow, it's the same thing (<<< and <<)...
Either way I have yet to meet anyone that needed to use the >>>, but I'm sure they are out there doing amazing things.
As you have just seen, the >> operator automatically fills the
high-order bit with its previous contents each time a shift occurs.
This preserves the sign of the value. However, sometimes this is
undesirable. For example, if you are shifting something that does not
represent a numeric value, you may not want sign extension to take
place. This situation is common when you are working with pixel-based
values and graphics. In these cases you will generally want to shift a
zero into the high-order bit no matter what its initial value was.
This is known as an unsigned shift. To accomplish this, you will use
java’s unsigned, shift-right operator,>>>, which always shifts zeros
into the high-order bit.
Further reading:
http://henkelmann.eu/2011/02/01/java_the_unsigned_right_shift_operator
http://www.java-samples.com/showtutorial.php?tutorialid=60
The signed right-shift operator is useful if one has an int that represents a number and one wishes to divide it by a power of two, rounding toward negative infinity. This can be nice when doing things like scaling coordinates for display; not only is it faster than division, but coordinates which differ by the scale factor before scaling will differ by one pixel afterward. If instead of using shifting one uses division, that won't work. When scaling by a factor of two, for example, -1 and +1 differ by two, and should thus differ by one afterward, but -1/2=0 and 1/2=0. If instead one uses signed right-shift, things work out nicely: -1>>1=-1 and 1>>1=0, properly yielding values one pixel apart.
The unsigned operator is useful either in cases where either the input is expected to have exactly one bit set and one will want the result to do so as well, or in cases where one will be using a loop to output all the bits in a word and wants it to terminate cleanly. For example:
void processBitsLsbFirst(int n, BitProcessor whatever)
{
while(n != 0)
{
whatever.processBit(n & 1);
n >>>= 1;
}
}
If the code were to use a signed right-shift operation and were passed a negative value, it would output 1's indefinitely. With the unsigned-right-shift operator, however, the most significant bit ends up being interpreted just like any other.
The unsigned right-shift operator may also be useful when a computation would, arithmetically, yield a positive number between 0 and 4,294,967,295 and one wishes to divide that number by a power of two. For example, when computing the sum of two int values which are known to be positive, one may use (n1+n2)>>>1 without having to promote the operands to long. Also, if one wishes to divide a positive int value by something like pi without using floating-point math, one may compute ((value*5468522205L) >>> 34) [(1L<<34)/pi is 5468522204.61, which rounded up yields 5468522205]. For dividends over 1686629712, the computation of value*5468522205L would yield a "negative" value, but since the arithmetically-correct value is known to be positive, using the unsigned right-shift would allow the correct positive number to be used.
A normal right shift >> of a negative number will keep it negative. I.e. the sign bit will be retained.
An unsigned right shift >>> will shift the sign bit too, replacing it with a zero bit.
There is no need to have the equivalent left shift because there is only one sign bit and it is the leftmost bit so it only interferes when shifting right.
Essentially, the difference is that one preserves the sign bit, the other shifts in zeros to replace the sign bit.
For positive numbers they act identically.
For an example of using both >> and >>> see BigInteger shiftRight.
In the Java domain most typical applications the way to avoid overflows is to use casting or Big Integer, such as int to long in the previous examples.
int hiint = 2147483647;
System.out.println("mean hiint+hiint/2 = " + ( (((long)hiint+(long)hiint)))/2);
System.out.println("mean hiint*2/2 = " + ( (((long)hiint*(long)2)))/2);
BigInteger bhiint = BigInteger.valueOf(2147483647);
System.out.println("mean bhiint+bhiint/2 = " + (bhiint.add(bhiint).divide(BigInteger.valueOf(2))));
I would think it is 00010010
i.e. it tries to maintain the sign bit as is
On the other hand, the logical left shift by 1 pos would be
10010010
Is this correct?
For left shift, arithmetic and logical shift are the same.
The difference is for right shift only, where an arithmetic right shift will copy the old MSB to the new MSB after having shifted, thus keeping a negative number from being converted to a positive when shifting.
Wikipedia has a more detailed explanation.
In Java << is a logical left-shift. 0 is always added as the LSB.
(Do note that Java will promote the [byte] value in question, so care must be taken to mask back to an octect! Otherwise you'll keep the shifted bit(s), which might have included "1".)
However, the Wikipedia article on Arithmetic shift indiciates that an arithmetic left shift may result in an overflow error:
...Note that arithmetic left shift may cause an overflow; this is the only way it differs from logical left shift.
(This is not the case in Java, but just to keep in mind.)
Happy coding.
Yes it is correct.
The arithmetic left shift of x by n places is equal to x * (2^n). So in your example is the ar-left-shift of 01001001 by 1 place equal to 10010010 (73 * 2¹ = 146).
You are correct when you left shift by 1 bit postion. It equals 10010010.
when you shift 4 bits to the left as follows, you get the following answer.
01001001 << 4 = 10010000
when you shift 4 bits to the right as follows, you get the following answer.
01001001 >> 4 = 00000100
Bits that are left empty as a result of shifting are filled with zeros.