I read some Java code and came across the | operator.
Can anyone what the operator is doing in this context?
for (int i=0; i<8; i++) {
x[i] = hexBytes[i*4] << 24
| hexBytes[i*4+1] << 16
| hexBytes[i*4+2] << 8
| hexBytes[i*4+3];
}
The bitwise OR (and AND) can be used for bit handling. AND allows you to extract a set of bits: int lowest8bits = 0xFFFFF & 0xFF;.
With OR you can insert bits. In the code above, 4 bytes are inserted to the same int by shifting them to the right position and ORing them.
10010010 byte
10010010 00000000 << 8
00000000 00000000 00000000 00010110 The int we're building
00000000 00000000 10010010 00010110 End result in int after OR
Operators used are:
"<< (left shift)" : Binary Left Shift Operator. The left operands
value is moved left by the number of bits specified by the right
operand.
">> (right shift)" : Binary Right Shift Operator. The left operands value is moved right by the number of bits specified by the
right operand.
"| (bitwise or)" : Binary OR Operator copies a bit if it exists in either operand.
In your code:
hexBytes[i*4] << 24
binary value of hexBytes[i*4] is left shifted by 24 bit. same with others and the result is OR by the bitwise | operator.
It's the bitwise or. See this article for more information: https://www.baeldung.com/java-bitwise-operators
3.1 refers to this specific operator. It also explains the left shift << operator
Related
It's add modulo 2^512. Could you explain me why we doing here >>8 and then &oxFF?
I know i'm bad in math.
int AddModulo512(int []a, int []b)
{
int i = 0, t = 0;
int [] result = new int [a.length];
for(i = 63; i >= 0; i--)
{
t = (a[i]) + (int) (b[i]) + (t >> 8);
result[i] = (t & 0xFF); //?
}
return result;
}
The mathematical effect of a bitwise shift right (>>) on an integer is to divide by two (truncating any remainder). By shifting right 8 times, you divide by 2^8, or 256.
The bitwise & with 0xFF means that the result will be limited to the first byte, or a range of 0-255.
Not sure why it references modulo 512 when it actually divides by 256.
It looks like you have 64 ints in each array, but your math is modulo 2^512. 512 divided by 64 is 8, so you are only using the least significant 8 bits in each int.
Here, t is used to store an intermediate result that may be more than 8 bits long.
In the first loop, t is 0, so it doesn't figure in the addition in the first statement. There's nothing to carry yet. But the addition may result in a value that needs more than 8 bits to store. So, the second line masks out the least significant 8 bits to store in the current result array. The result is left intact to the next loop.
What does the previous value of t do in the next iteration? It functions as a carry in the addition. Bit-shifting it to the right 8 positions makes any bits beyond 8 in the previous loop's result into a carry into the current position.
Example, with just 2-element arrays, to illustrate the carrying:
[1, 255] + [1, 255]
First loop:
t = 255 + 255 + (0) = 510; // 1 11111110
result[i] = 510 & 0xFF = 254; // 11111110
The & 0xFF here takes only the least significant 8 bits. In the analogy with normal math, 9 + 9 = 18, but in an addition problem with many digits, we say "8 carry the 1". The bitmask here performs the same function as extracting the "8" out of 18.
Second loop:
// 1 11111110 >> 8 yields 0 00000001
t = 1 + 1 + (510 >> 8) = 1 + 1 + 1 = 3; // The 1 from above is carried here.
result[i] = 3 & 0xFF = 3;
The >> 8 extracts the possible carry amount. In the analogy with normal math, 9 + 9 = 18, but in an addition problem with many digits, we say "8 carry the 1". The bit shift here performs the same function as extracting the "1" out of 18.
The result is [3, 254].
Notice how any carry leftover from the last iteration (i == 0) is ignored. This implements the modulo 2^512. Any carryover from the last iteration represents 2^512 and is ignored.
>> is a bitwise shift.
The signed left shift operator "<<" shifts a bit pattern to the left,
and the signed right shift operator ">>" shifts a bit pattern to the
right. The bit pattern is given by the left-hand operand, and the
number of positions to shift by the right-hand operand. The unsigned
right shift operator ">>>" shifts a zero into the leftmost position,
while the leftmost position after ">>" depends on sign extension.
& is a bitwise and
The bitwise & operator performs a bitwise AND operation.
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html
http://www.tutorialspoint.com/java/java_bitwise_operators_examples.htm
>> is the bitshift operator
0xFF is the hexadecimal literal for 255.
I think your question misses a very important part, the data format, i.e. how data are stored in a[] and b[]. To solve this question, I make some assumptions:
Since it's modulo arithmetic, a, b <= 2^512. Thus, a and b have 512 bits.
Since a and b have 64 elements, only 8 right-most bits of each elements are used. In other words, a[i], b[i] <= 256.
Then, what remains is very straightforward. Just consider each a[i] and b[i] as a digit (each digit is 8-bit) in a base 2^512 addition and then perform addition by adding digit-by-digit from right-to-left.
t is the carry variable which stores the value (with carry) of the addition at the last digit. t>>8 throws a way the right-most 8 bits that has been used for the last addition which is used as carry for the current addition. (t & 0xFF) gets the right-most 8 bits of t which is used for the current digit.
Since it's modulo addition, the final carry is thrown away.
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.
This question already has answers here:
What does << mean in Java?
(8 answers)
Closed 8 years ago.
i was working through the following oracle java class and came across this line of code:
public synchronized int getRGB() {
return ((red << 16) | (green << 8) | blue);
}
I am lost as to what "<<" means, I also don't know what the return statement is suppose to return
It is a bit shift operation. Read more here. It will pack these 3 numbers into one integer.
24 bit colors are often represented as RRRRRRRRGGGGGGGGBBBBBBBB, with 8 bit values for each color. Your code takes the red value, shifts it 16 bits, shifts the green value 8 bits, and keeps the blue value unshifted, then performs a logical OR, which in this case is the same as adding the values. Think of it this way:
Your byte values for each color:
Red = 00011010
Green = 10101010
Blue = 11111111
The shifted values become:
Red << 16 =
00011010 00000000 00000000
Green << 8 =
00000000 10101010 00000000
Blue =
00000000 00000000 11111111
The logical OR combines them into:
00011010 10101010 11111111
which is your 24 bit RGB value, which is returned.
public synchronized int getRGB() {
return ((red << 16) | (green << 8) | blue);
}
I am lost as to what "<<" means, I also don't know what the return statement is suppose to return?
First off, the '<<' is called a bit shift operator. There is a fantastic write-up about them located here.
As to your second question, look at the signature of the method... it's going to return an int. BUT, in this case, it is going to return and int containing the value of blue and the bit shifted values of red and green.
Hope this helps!
x << y means "shift binary representation of x to left y places"
For instance
System.out.println(4 << 2);
will print 16.
4 is 100 in binary. If you shift 100 to the left 2 places, you get 10000 which is 16 in decimal.
In Java:
(0xFFFFFFFF << 1) = 0xFFFFFFFE = 0b1111111111111110
: : :
(0xFFFFFFFF << 30) = 0xE0000000 = 0b1110000000000000
(0xFFFFFFFF << 30) = 0xC0000000 = 0b1100000000000000
(0xFFFFFFFF << 31) = 0x80000000 = 0b1000000000000000
However:
(0xFFFFFFFF << 32) = 0xFFFFFFFF = 0b1111111111111111
Logically this makes no sense, but what I believe to be happening is Java performing an operation similar to:
a << (b % Integer.SIZE) [edit, apparently:] a << (b & 0x1F)
This applies to >> and >>>, too.
Obviously shifting by >= 32 (in the case of an Integer) removes all data from the data-type, but there are times when this is useful. For example:
int value = 0x3F43F466; // any value
int shift = 17; // any value >= 0
int carry = value & (-1 << (Integer.SIZE - shift));
if (carry > 0)
; // code...
Of course this can be fixed, but finding these bugs can be quite time consuming (I just spent hours tracking a similar one down).
So, my question: Is there reason for not returning the logical value when shifting all bits out?
UPDATE:
I tried this in C99, using the following:
#include<stdio.h>
main()
{
int i, val;
for (i = 0; i <=36; i++) {
val = (-1 << i);
printf("%d :\t%d\n", i, val);
}
}
I found that it behaves the same as Java, masking i & 0x1F, whereas it provides a warning at compilation when given a constant value:
warning: left shift count >= width of type
Sure, there is: it's how most processors (specifically including x86) implement bit shifting, and to do what you want -- to check if the shift is greater than 32, and if so, return zero -- requires a branch, which can be expensive on modern CPUs. It's not just "annoying," it can slow things down by orders of magnitude.
In short, doing what you want would add significant overhead to an operation that is expected to be blazing fast by high-performance code.
For reference, the logic isn't exactly the same as %, it's a mask. See JLS 15.19 for details:
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.
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
to put it simply 0xFFFFFFFF << 32 is equivalnt to 0xFFFFFFFF << (32 & 0x1f) is equivalent to 0xFFFFFFFF << 0
What is the difference between >>> and >> operators in Java?
>> is arithmetic shift right, >>> is logical shift right.
In an arithmetic shift, the sign bit is extended to preserve the signedness of the number.
For example: -2 represented in 8 bits would be 11111110 (because the most significant bit has negative weight). Shifting it right one bit using arithmetic shift would give you 11111111, or -1. Logical right shift, however, does not care that the value could possibly represent a signed number; it simply moves everything to the right and fills in from the left with 0s. Shifting our -2 right one bit using logical shift would give 01111111.
>>> is unsigned-shift; it'll insert 0. >> is signed, and will extend the sign bit.
JLS 15.19 Shift Operators
The shift operators include left shift <<, signed right shift >>, and unsigned right shift >>>.
The value of n>>s is n right-shifted s bit positions with sign-extension.
The value of n>>>s is n right-shifted s bit positions with zero-extension.
System.out.println(Integer.toBinaryString(-1));
// prints "11111111111111111111111111111111"
System.out.println(Integer.toBinaryString(-1 >> 16));
// prints "11111111111111111111111111111111"
System.out.println(Integer.toBinaryString(-1 >>> 16));
// prints "1111111111111111"
To make things more clear adding positive counterpart
System.out.println(Integer.toBinaryString(121));
// prints "1111001"
System.out.println(Integer.toBinaryString(121 >> 1));
// prints "111100"
System.out.println(Integer.toBinaryString(121 >>> 1));
// prints "111100"
Since it is positive both signed and unsigned shifts will add 0 to left most bit.
Related questions
Right Shift to Perform Divide by 2 On -1
Is shifting bits faster than multiplying and dividing in Java? .NET?
what is c/c++ equivalent way of doing ‘>>>’ as in java (unsigned right shift)
Negative logical shift
Java’s >> versus >>> Operator?
What is the difference between the Java operators >> and >>>?
Difference between >>> and >> operators
What’s the reason high-level languages like C#/Java mask the bit shift count operand?
1 >>> 32 == 1
>>> will always put a 0 in the left most bit, while >> will put a 1 or a 0 depending on what the sign of it is.
They are both right-shift, but >>> is unsigned
From the documentation:
The unsigned right shift operator ">>>" shifts a zero into the leftmost position, while the leftmost position after ">>" depends on sign extension.
The logical right shift (v >>> n) returns a value in which the bits in v have been shifted to the right by n bit positions, and 0's are shifted in from the left side. Consider shifting 8-bit values, written in binary:
01111111 >>> 2 = 00011111
10000000 >>> 2 = 00100000
If we interpret the bits as an unsigned nonnegative integer, the logical right shift has the effect of dividing the number by the corresponding power of 2. However, if the number is in two's-complement representation, logical right shift does not correctly divide negative numbers. For example, the second right shift above shifts 128 to 32 when the bits are interpreted as unsigned numbers. But it shifts -128 to 32 when, as is typical in Java, the bits are interpreted in two's complement.
Therefore, if you are shifting in order to divide by a power of two, you want the arithmetic right shift (v >> n). It returns a value in which the bits in v have been shifted to the right by n bit positions, and copies of the leftmost bit of v are shifted in from the left side:
01111111 >> 2 = 00011111
10000000 >> 2 = 11100000
When the bits are a number in two's-complement representation, arithmetic right shift has the effect of dividing by a power of two. This works because the leftmost bit is the sign bit. Dividing by a power of two must keep the sign the same.
Read more about Bitwise and Bit Shift Operators
>> Signed right shift
>>> Unsigned right shift
The bit pattern is given by the left-hand operand, and the number of positions to shift by the right-hand operand. The unsigned right shift operator >>> shifts a zero into the leftmost position,
while the leftmost position after >> depends on sign extension.
In simple words >>> always shifts a zero into the leftmost position whereas >> shifts based on sign of the number i.e. 1 for negative number and 0 for positive number.
For example try with negative as well as positive numbers.
int c = -153;
System.out.printf("%32s%n",Integer.toBinaryString(c >>= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c <<= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c >>>= 2));
System.out.println(Integer.toBinaryString(c <<= 2));
System.out.println();
c = 153;
System.out.printf("%32s%n",Integer.toBinaryString(c >>= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c <<= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c >>>= 2));
System.out.printf("%32s%n",Integer.toBinaryString(c <<= 2));
output:
11111111111111111111111111011001
11111111111111111111111101100100
111111111111111111111111011001
11111111111111111111111101100100
100110
10011000
100110
10011000
The right shift logical operator (>>> N) shifts bits to the right by N positions, discarding the sign bit and padding the N left-most bits with 0's. For example:
-1 (in 32-bit): 11111111111111111111111111111111
after a >>> 1 operation becomes:
2147483647: 01111111111111111111111111111111
The right shift arithmetic operator (>> N) also shifts bits to the right by N positions, but preserves the sign bit and pads the N left-most bits with 1's. For example:
-2 (in 32-bit): 11111111111111111111111111111110
after a >> 1 operation becomes:
-1: 11111111111111111111111111111111
>> Signed right shift
>>> Unsigned right shift
Example:-
byte x, y; x=10; y=-10;
SOP("Bitwise Left Shift: x<<2 = "+(x<<2));
SOP("Bitwise Right Shift: x>>2 = "+(x>>2));
SOP("Bitwise Zero Fill Right Shift: x>>>2 = "+(x>>>2));
SOP("Bitwise Zero Fill Right Shift: y>>>2 = "+(y>>>2));
output would be :-
Bitwise Left Shift: x<<2 = 40
Bitwise Right Shift: x>>2 = 2
Bitwise Zero Fill Right Shift: x>>>2 = 2
Bitwise Zero Fill Right Shift: y>>>2 = 1073741821
>>(signed) will give u different result for 8 >> 2, -8 >> 2.
right shift of 8
8 = 1000 (In Binary)
perform 2 bit right shift
8 >> 2:
1000 >> 2 = 0010 (equivalent to 2)
right shift of -8
8 = 1000 (In Binary)
1's complement = 0111
2's complement:
0111 + 1 = 1000
Signed bit = 1
perform 2 bit right shift (on 2's co result)
8 >> 2:
1000 >> 2 = 1110 (equivalent to -2)
>>(unsigned) will give u same result for 8 >>> 2, -8 >>> 2.
unsigned right shift of 8
8 = 1000
8 >>> 2 = 0010
unsigned right shift of -8
-8 = 1000
-8 >>> 2 = 0010