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

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.

Related

Bitwise operation && overflow [duplicate]

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.

Can someone please explain why 4 & 0xFFFF - 1 is still 4? [duplicate]

This question already has an answer here:
Java Precedence - Casting and Bitwise Operators
(1 answer)
Closed 2 years ago.
System.out.println(4 & 0xFFFF);
System.out.println(4 & 0xFFFF - 1);
int i = 4 & 0xFFFF;
System.out.println(i - 1);
I tried these four lines. But the first and second print will all print out 4. However, the last one will print out 3. I really cannot figure out why... shouldn't the second print prints out 3?
Use () to make it clear what you expect to be the order of operation:
System.out.println( 4 & (0xFFFF - 1) );
System.out.println( (4 & 0xFFFF) - 1 );
Without the () the order of operation is the first case;

Bitwise operation in ActionScript 3 compare to Java

I am researching this AS3 code that write a BitString into a ByteArray. Source: JPGEncoder#writeBits()
private var byteout:ByteArray;
private var bytenew:int = 0;
private var bytepos:int = 7;
private function writeBits(bs:BitString):void
{
var value:int = bs.val;
var posval:int = bs.len-1;
while (posval >= 0) {
if (value & uint(1 << posval)) {
bytenew |= uint(1 << bytepos);
}
posval--;
bytepos--;
if (bytepos < 0) {
if (bytenew == 0xFF) {
writeByte(0xFF);
writeByte(0);
} else {
writeByte(bytenew);
}
bytepos=7;
bytenew=0;
}
}
}
But I don't understand part of the code.
What is uint(1 << bytepos)?
What is the if condition if (value & uint(1 << posval))?
I don't know whether the & is "and" bit operator, or "and" condition.
Does if(number) in AS3 means if(number != 0) ?
What is these AS3 code equivalent in Java?
Bitwise operations in Java are somewhat awkward, because Java has no unsigned types.
So when you intend to work with bytes, you should make sure you stay with bytes. Things like 0x0f | 0x80 -> 0b1000 1111 done with bytes must be cast to bytes all the time:
System.out.printf("%x - %x - (byte)%x - (int)%x\n",
(byte)0x80,
(byte)0xf,
(byte)((byte)0x80|(byte)0xf),
(int)((byte)0x80|(byte)0xf));
OUTPUT:
80 - f - (byte)8f - (int)ffffff8f
Having said this, you may want to work with ints from the beginning and cast to bytes later.
The code you present transcribes the BitString into a bit stream cut into bytes.
A special case is handled if all bits of a byte are set, in that case 0xff00 is output.
What is uint(1 << bytepos)?
This moves the lhs of the operator by bytepos bits to the left:
1 << 4 -> 0b00010000
What is the if condition if (value & uint(1 << posval))?
I don't know whether the & is "and" bit operator, or "and" condition.
& is bitwise AND, && is boolean.
The operation is != 0 -> TRUE if the bit at posval position is set. This is the condition to set the corresponding bit in the byte.
Transferring the code to Java should be straightforward actually. I would suggest you use plain int in java and convert to byte just before you write:
byte realByte = (byte)(intbyte & (byte)0xff);
writeByte(realByte);
This way, you avoid constant casting to byte and you avoid the above mentioned problem with negative bytes.
I believe these are the bit shift operators of AS3. You will find that Java uses the same syntax.
This link about bit operations in AS3. The Java documentation page here explains what the operators do.
As for the if condition, it checks if the 'posval'-th bit from the right in value is 1. It "selects" the bit by applying the bitwise and between value and the shifting of value 1 ( 000...01 in binary) by posval bits.

Bitwise differences in Java/Perl

I was messing around and noticed differences that I don't understand between Java and Perl when I bit-shifted -1.
I thought integers are stored in two's complement binary, so if there are 32 bits, -1 is 11...11 (32 times).
I'd expect -1 >> 1 to give $2^31 - 1$ = 011...11 = 2147483647.
I'd expect -1 << 1 to give = 11...110 = -2.
What is the reason for these different behaviors and where are these standards stated in different languages?
Code and printouts for Perl & Java below:
In Perl:
print (-1 >> 1, "\n");
print (-1 << 1, "\n");
2147483647
4294967294
In Java:
public class Tempy {
public static void main(String[] args){
System.out.println( -1 >> 1);
System.out.println( -1 << 1);
}
}
-1
-2
Perl's bit shift is inherently unsigned so -1 is treated as 2^32 -1 and it automatically fills with 0 so -1 >> 1 is 2^31-1 and -1 << 1 is 2^32-2.
[Edit] Thanks #Powerlord using integer will force perl to use signed values.
Java's bit shift sign extends (if using >>) so -1 << 1 is still -1 and -1 >> 1 is -2. If you don't want to sign extend you have to use the logical version >>>.

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.

Categories