having trouble understanding code, specifically the & - java

I am reading a tutorial regarding a Java pacman game.
Here is the code in question.
if (pacmanx % blocksize == 0 && pacmany % blocksize == 0) {
pos = // integer
ch = screendata[pos];
if ((ch & 16) != 0) { // do not understand this.
screendata[pos] = (short)(ch & 15);
...
}
I am not really understanding the single &. I understand this operand checks both sides of an if statement, or is a bitwise operator. However, per the tests below, it doesn't seem to be either:
if I was to test (ch = 18):
(ch & 16) = 16
(ch & 8) = 0
(ch & 2) = 2
thanks

& is the bitwise operator AND:
18 = 10010
16 = 10000
----------
16 = 10000
18 = 10010
8 = 01000
----------
0 = 00000
So the if will check if the fifth bit is 1 or 0.

That's not a Boolean and, which is always &&; instead it's a bitwise and. It's checking to see if the 5th bit from the right is set in ch.
ch = 18 // ch = 0b00010100
ch & 16 // 16 = 0b00010000
// ch & 16 = 0b00010000 != 0
ch & 8 // 8 = 0b00001000
// ch & 8 = 0b00000000 == 0
ch & 2 // 2 = 0b00000010
// ch & 2 = 0b00000010 != 0

The single & it's a bitwise AND. It's an and operation performed on individual bit of your number.
Consider a possible bit representation of your short:
10011011 & : screendata[pos]
00010000 = : 16
----------
10010000
Specifically this line:
if ((ch & 16) != 0) {
check if the 5-th bit (2^ (5 -1)) of your number is set to 1 (different from 0).

Given ch = 18
(ch & 16) = 16
(ch & 8) = 0
(ch & 2) = 2
seems correct. What's 18 in binary ? 16 | 2 or 10010 in binary.
To be clear, & is a bitwise operator. However && returns true if both operands are true.

Single ampersand is a bitwise AND operator.
You might find it easier to "get" if the values were in hex.

The bitwise and operator & performs an "and" on each bit of the two integers to determine the result.
So:
18 = 0001 0010
16 = 0001 0000
18&16 = 0001 0000

& is bitwise operator AND. You can see detail in http://docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html

Related

Understanding how bit-shifting works with Negative Shift Values in Java

I am writing a simple program to determine unique characters in a string. I can do this an easier, less efficient way using an Array, but I am trying to implement it using a bit vector. I am able to get correct output fine but I am unsure about why I get the correct output.
My code:
class Main {
public static void main(String args[]) {
System.out.println(isUniqueChars("Robert"));
}
public static boolean isUniqueChars(String str) {
int checker = 0;
for (int i = 0; i < str.length(); i++) {
int val = str.charAt(i) - 'a';
System.out.println("Val: " + val); //Val = -15 First Iteration
System.out.print("1 << val: "); //Equals 131072
System.out.println(1 << val);
if ((checker & (1 << val)) > 0) {
return false;
}
System.out.print("Checker: ");
checker = checker | (1 << val);
System.out.println(checker); //Equals 131072
System.out.println();
}
return true;
}
}
I am trying to figure out why 1 << -15 yields 131072. I have searched the internet and have watched a couple of tutorials on shift operators but none of them explain negative shift values.
From the JLS:
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 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.
The constant 1 is an int, so the -15, which is 0xfffffff1 is masked to 0x00000011 indicating a left shift of 17 bits, which is exactly 131072.
One way of looking at it is the bits are shifted in a positive modulo 32 fashion. So what positive number between 0 and 32 is congruent to -15 mod 32? By adding 32 to -15 you get 17. So it's the same as shifting by 17. In fact shifting -15 + k*32 where k is an integer will shift the same amount of bits as shown below.
int k = 4;
int v = 1;
for (int i = -15+(32*-k); i < -15+(32*k); i+= 32) {
int res = v << i;
System.out.printf("1 << %4d == %d%n", i, res );
}
prints
1 << -143 == 131072
1 << -111 == 131072
1 << -79 == 131072
1 << -47 == 131072
1 << -15 == 131072
1 << 17 == 131072
1 << 49 == 131072
1 << 81 == 131072
This also means you can't clear an int by << 32. You need to left shift 31 and then left shift 1. Or more generally, left shift by k and then left shift by 32-k where 1 <= k < 32.
int k = 98;
System.out.println(k<<32); // really shifts by 0
System.out.println((k<<31)<<1));
Prints
98
0
The same rules apply to long with 32 being replaced by 64.

JAVA CRC16 function returns a 3 characters response instead of 4

I have a Java CRC16 function like below and I need it to return a 4 length alphanumeric result. But sometimes it returns only a 3 length alphanumeric. Why? I am cross comparing this CRC with a C application that calculates the CRC and usually it is the same CRC but from time to time the JAVA returns a 3 character result which raises an exception. Why?
int crrc = 0xFFFF; // initial value
int polynomial = 0x1021; // 0001 0000 0010 0001 (0, 5, 12)
String str = "0009";
byte []by = x; // x is the byte array from args
for (byte b : by) {
for (int i = 0; i < 8; i++) {
boolean bit = ((b >> (7-i) & 1) == 1);
boolean c15 = ((crrc >> 15 & 1) == 1);
crrc <<= 1;
if (c15 ^ bit) crrc ^= polynomial;
}
}
crrc &= 0xffff;
System.out.println(crrc);
System.out.println("CRC16-CCITT = " + Integer.toHexString(crrc) + " " + Integer.toHexString(crrc).length());
You're receiving ArrayIndexOutOfBoundException probably, so I think the hex value might have zero in its most significant nibble. Try to find out those values(x) and check whether (x >>> 12) == 0 or (x & 0xf000) == 0. If this returns true, you can pad your string with necessary number of 0s from the left.
One possible way: String.format("%04d", crrc)

Meaning of << and |= in Java

There is a question of implementing a code in Java where I have to find if the string has unique characters or not without having to create a new data structure.
The Java implementation was as follows:
public static boolean isUniqueChars(String str) {
int checker = 0;
for (int i = 0; i < str.length(); ++i) {
int val = str.charAt(i) - 'a';
if ((checker & (1 << val)) > 0) return false;
checker |= (1 << val);
}
return true;
}
In line 5-6, there's the << that I don't really get.
And in line 6, I don't get what the '|' symbol does.
Could someone give a brief explanation of how this code works?
Thanks.
1. For this symbol : <<
In your code : 1 << val means (int)Math.pow(2,val) = 2 ^ val
2. For this symbol : >>
>> is bit-shift operator
x >> N means (if you view it as a string of binary digits):
The rightmost N bits are discarded
The leftmost bit is replicated as many times as necessary to pad the result to the original size (32 or 64 bits),
e.g.
00000000000000000000000000101011 >> 2 -> 00000000000000000000000000001010
11111111111111111111111111010100 >> 2 -> 11111111111111111111111111110101
3. For this symbol : |=
it means bitwise inclusive OR and assignment operator
E.g:
checker |= (1<<val)
is same as checker |= (2^val)
is same as checker = checker | (2^val) (*)
then : A | B ( | means Binary OR Operator copies a bit if it exists in either operand)
Example
A = 00101010
B = 01101000
A | B = 01101010
with
0 OR 0 = 0 , 1 OR 0 = 1
1 OR 1 = 1 , 0 OR 1 = 1
Using Ziprox's helpful hint that (1 << val) is equivalent to 2^val or Math.pow(2,val). It becomes much easier to decipher what is happening.
I believe 'int' is 4 bytes long which is 32 bits. This method is converting each letter in the alphabet (undercase) to number 2 ^ val. Basically, each letter is represented by a unique bit of the variable checker. 26 letters, 32 bits gives you 6 extra bits that do nothing.
checker & (1<<val)
will only be true of it has seen the number previously.
checker |= (1<<val)
is equivalent to
checker = (checker | (1<<val))
which simply flips that letter's bit from 0 to 1 to indicate that it has been seen.

How to find most significant bit (MSB)

I want to know which value the first bit of a byte has.
For example:
I have byte m = (byte) 0x8C;
How could I know if the first bit is an 1 or a 0 ?
Can anyone help me out ?
It depends what you mean by "first bit". If you mean "most significant bit" you can use:
// 0 or 1
int msb = (m & 0xff) >> 7;
Or if you don't mind the values being 0x80 or 0, just use:
// 0 or 0x80
int msb = m & 0x80;
Or in fact, as a boolean:
// Uses the fact that byte is signed using 2s complement
// True or false
boolean msb = m < 0;
If you mean the least significant bit, you can just use:
// 0 or 1
int lsb = m & 1;
If the first bit is the lowest bit (ie bit 0), then
if((m & 1) >0) ...
should do it.
In general,
if ((m & (1<<N)) > 0) ...
will give you whether or not bit N is set.
If, however, you meant the highest bit (bit 7), then use N=7.
Assuming you mean leftmost bit, bitwise and it with 0x80 and check if it is zero nor not:
public boolean isFirstBitSet(byte b) {
System.out.println((b & (byte)0x80));
return (b & (byte)0x80) < 0;
}
If you mean lowest order bit you will need to and with 0x01 and check a different condition:
public boolean isFirstBitSet(byte b) {
System.out.println((b & (byte)0x01));
return (b & (byte)0x80) > 0;
}
Use the bitwise and operator.
public class BitExample {
public static void main(String args[]) throws Exception {
byte m = (byte)0x8C;
System.out.println("The first bit is " + (m & (byte)0x01));
m = (byte)0xFF;
System.out.println("The first bit is " + (m & (byte)0x01));
}
}
// output is...
The first bit is 0
The first bit is 1
Its a bit of a hack but you can use
if(x >> -1 != 0) // top bit set.
This works for byte, short, int, long data types.
However for most types the simplest approach is to compare with 0
if (x < 0) // top bit set.
This works for byte, short, int, long, float, or double
(Ignoring negative zero and negative NaN, most people do ;)
For char type you need to know the number of bits. ;)
if (ch >>> 15 != 0) // top bit set.
This code gives you msb(most significant bit)/biggest number which is a
power of 2 and less than any given number.
class msb{
void main(){
int n=155;//let 110001010
int l=(Integer.toBinaryString(n)).length();//9
String w="0"+Integer.toBinaryString(i).substring(1);//010001010
i=Integer.parseInt(w,2);
System.out.println(n^i);//110001010^010001010=100000000
}
}

can't == be used instead of unary & to check if two values are equal

Recently I came across a code snippet in a book which sets a Boolean value to a field like this
the input identifier is a List of Strings
if (identifier.size() >= 2) {
int c = Integer.parseInt(identifier.get(1));
bulk = (c & 4) == 4;
hazardous = (c & 2) == 2;
toxic = (c & 1) == 1;
}
what is the need for unary & operators here?Can't this be done using a simple
c==4 etc instead of (c & 4)== 4 ?
No, this is a bitwise operation.
Imagine c=7. In that case all conditions would be true.
c = 7;
bulk = (c & 4) == 4; // true
hazardous = (c & 2) == 2; //true
toxic = (c & 1) == 1; //true
In binary, you'd have this:
c = 0111; //4-bit to simplify output
bulk = (c & 0100) == 0100; //
hazardous = (c & 0010) == 0010; //true
toxic = (c & 0001) == 0001; //true
Due to bitwise AND (&) you get 0111 & 0010 = 0010 etc.
This is added for bit masking
if
c =3 then also it will be considered as toxic with this
toxic = (c & 1) == 1;
if you write
toxic = c == 1;
then it would be stcict 1 check
The variable c is clearly a bitmask. The effect of doing the bitwise & is mask off the other bits, leaving just the one bit still set. For example, this statement:
bulk = (c & 4) == 4;
tests if bit 2 of c is set (and doesn't care about the other bits) - bit 2 being the 1 bit in this byte: 00000100
c == 4 checks if c equals 4, meaning the binary form of c is 000...00100. (c & 4) == 4 if the binary form of c is the following xxx...xx1xx.

Categories

Resources