I came across the following program and it behaving in unexpected manner.
public class ShiftProgram
{
public static void main(String[] args)
{
int i = 0;
while(-1 << i != 0)
i++;
System.out.println(i);
}
}
If we think about this program output, when it reaches 32 while loop condition should return false and terminate and it should print 32.
If you ran this program, it does not print anything but goes into an infinite loop. Any idea whats going on? Thank you in advance.
Have you tried printing out (-1 << i) in the loop to see what's going wrong? If you do, you'll see that it goes:
-1 << 0 = -1
-1 << 1 = -2
-1 << 2 = -4
-1 << 3 = -8
-1 << 4 = -16
-1 << 5 = -32
-1 << 6 = -64
-1 << 7 = -128
-1 << 8 = -256
-1 << 9 = -512
-1 << 10 = -1024
-1 << 11 = -2048
-1 << 12 = -4096
-1 << 13 = -8192
-1 << 14 = -16384
-1 << 15 = -32768
-1 << 16 = -65536
-1 << 17 = -131072
-1 << 18 = -262144
-1 << 19 = -524288
-1 << 20 = -1048576
-1 << 21 = -2097152
-1 << 22 = -4194304
-1 << 23 = -8388608
-1 << 24 = -16777216
-1 << 25 = -33554432
-1 << 26 = -67108864
-1 << 27 = -134217728
-1 << 28 = -268435456
-1 << 29 = -536870912
-1 << 30 = -1073741824
-1 << 31 = -2147483648
-1 << 32 = -1
-1 << 33 = -2
-1 << 34 = -4
-1 << 35 = -8
-1 << 36 = -16
[.. etc ..]
According to the language specification:
The value of n<<s is n left-shifted s bit positions; this is equivalent (even if overflow occurs) to multiplication by two to the power s.
... so the result will always remain negative.
That document also tells you that:
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. The shift distance actually used is therefore always in the range 0 to 31, inclusive.
So if you use a shift of 32, that's interpreted as a shift of 32 & 0x1f, which is 0. -1 shifted by 0 is still just -1, not 0.
The shift count is interpreted modulo the number of bits in an int (32), and so i << 32 is just i << 0 which is i. Thus, you will never get 0 as the result. My source for that is http://www.janeg.ca/scjp/oper/shift.html. If you do something like int n = -1; while (n != 0) {i++; n <<= 1;}, it will eventually reach 0 like you want.
Related
I am currently trying to make my chess engine faster, and am looking at implementing magic bitboards for my sliding piece attack generation. I am using a bitboard representation of the chessboard with the a1 square being the furthest right bit, and h8 being the furthest left. I am looking at this site:
https://rhysre.net/fast-chess-move-generation-with-magic-bitboards.html#:~:text=A%20bitboard%20is%20simply%20a,and%20bit%2063%20%3D%20h8)
Specifically the code snippet found towards the bottom of the page that reads:
U64 getBishopAttacksMagic(int square, U64 blockers) {
// Mask blockers to only include bits on diagonals
blockers &= BISHOP_MASKS[square];
// Generate the key using a multiplication and right shift
U64 key = (blockers * BISHOP_MAGICS[square]) >> (64 - BISHOP_INDEX_BITS[square]);
// Return the preinitialized attack set bitboard from the table
return BISHOP_TABLE[square][key];
}
I already have Shallow blues magic numbers(each number corresponding to a square), and I already have pre initialized attack masks for the bishop piece stored in a 64 length array(again each number corresponding to a square). So i know how to get the key. But how do I generate the last array which takes the key, "BISHOP_TABLE" array? I do not understand how to generate that 2d array given an attack mask and magic number for each square. Thank you for your help in advance.
For each square, you need to generate every permutation of blocking pieces inside the bishop mask. For example, using this mask for the square e4 (#28):
8 | 0 0 0 0 0 0 0 0
7 | 0 1 0 0 0 0 0 0
6 | 0 0 1 0 0 0 1 0
5 | 0 0 0 1 0 1 0 0
4 | 0 0 0 0 0 0 0 0
3 | 0 0 0 1 0 1 0 0
2 | 0 0 1 0 0 0 1 0
1 | 0 0 0 0 0 0 0 0
---------------
a b c d e f g h
since there are 9 set bits, there are 2^9 = 512 different patterns of blocking pieces. The permutation number 339 (as binary = 0b101010011) looks like this:
8 | 0 0 0 0 0 0 0 0
7 | 0 1 0 0 0 0 0 0
6 | 0 0 1 0 0 0 0 0
5 | 0 0 0 1 0 0 0 0
4 | 0 0 0 0 0 0 0 0
3 | 0 0 0 0 0 0 0 0
2 | 0 0 1 0 0 0 1 0
1 | 0 0 0 0 0 0 0 0
---------------
a b c d e f g h
Bits are read from right (lsb) to left (msb) in the number and are set in the mask from the a file to the h file, 1st rank to 8th. Permutation 0 is an empty board and 511 (0b111111111) is the full mask.
Here's a method that takes a permutation number along with the bishop mask and returns the corresponding blockers bitboard:
private static long blockersPermutation(int iteration, long mask) {
long blockers = 0;
while (iteration != 0) {
if ((iteration & 1) != 0) {
int shift = Long.numberOfTrailingZeros(mask);
blockers |= (1L << shift);
}
iteration >>>= 1;
mask &= (mask - 1); // used in Kernighan's bit count algorithm
// it pops out the least significant bit in the number
}
return blockers;
}
Using this we can calculate the keys with both the magic numbers and the blockers, and we can create their corresponding values, the attack masks.
For each permutation of blocking pieces, create the corresponding attack mask and store it in the table. Include the blocking pieces and the squares on the side of the board in the mask. The attack mask for the blockers #339 on square #28 is:
8 | 0 0 0 0 0 0 0 0
7 | 0 0 0 0 0 0 0 1
6 | 0 0 0 0 0 0 1 0
5 | 0 0 0 1 0 1 0 0
4 | 0 0 0 0 0 0 0 0
3 | 0 0 0 1 0 1 0 0
2 | 0 0 1 0 0 0 1 0
1 | 0 0 0 0 0 0 0 0
---------------
a b c d e f g h
Here's a Java method to initialize the 64 bishop lookup tables:
private final long[][] BISHOP_LOOKUP = new long[64][512];
private static int getFile(int square) {
return square % 8;
}
private static int getRank(int square) {
return square / 8;
}
private static int getSquare(int rank, int file) {
return rank * 8 + file;
}
// just like the code snippet, generates the key
private static int transform (long blockers, long magic, int shift) {
return (int) ((blockers * magic) >>> (64 - shift));
}
private void initBishopLookup() {
for (int square = 0; square < 64; square++) {
long mask = BISHOP_MASKS[square];
int permutationCount = (1 << Long.bitCount(mask));
for (int i = 0; i < permutationCount; i++) {
long blockers = blockersPermutation(i, mask);
long attacks = 0L;
int rank = getRank(square), r;
int file = getFile(square), f;
for (r = rank + 1, f = file + 1; r <= 7 && f <= 7; r++, f++) {
attacks |= (1L << getSquare(r, f));
if ((blockers & (1L << getSquare(r, f))) != 0) {
break;
}
}
for (r = rank - 1, f = file + 1; r >= 0 && f <= 7; r--, f++) {
attacks |= (1L << getSquare(r, f));
if ((blockers & (1L << getSquare(r, f))) != 0) {
break;
}
}
for (r = rank - 1, f = file - 1; r >= 0 && f >= 0; r--, f--) {
attacks |= (1L << getSquare(r, f));
if ((blockers & (1L << getSquare(r, f))) != 0) {
break;
}
}
for (r = rank + 1, f = file - 1; r <= 7 && f >= 0; r++, f--) {
attacks |= (1L << getSquare(r, f));
if ((blockers & (1L << getSquare(r, f))) != 0) {
break;
}
}
int key = transform(blockers, BISHOP_MAGICS[square], Long.bitCount(mask));
BISHOP_LOOKUP[square][key] = attacks;
}
}
}
This uses plain magic bitboards with fixed size lookup tables, all of length 512 when masks with less set bits could fit in less space. Like on square b1 the mask uses 5 bits on the diagonal and the table could fit in an array of length 2^5 = 32. We're wasting (512 - 32) * (8 bytes per 64 bits number) / 1024 bytes per Kio = 3.75Kio for this square. Plain magic bitboards take 2Mib of memory for rooks and 256Kib for bishops, using fancy magic bitboards can reduce the total to ~800Kib. It's not really needed though, 2.25Mib of memory is small.
I have this function to find log of base 2 but I dont understand the meaning of the 31.
public static void loggg(int n){
int result = 0;
for(int i = 0; (n << i & 1 << 31) == 0; i++){
result = (31-i-1);
System.out.println( "result " +result);
}
}
this is my output. it seems like its a max number.
result 30
result 29
result 28
result 27
result 26
result 25
result 24
result 23
result 22
result 21
result 20
result 19
result 18
result 17
result 16
result 15
result 14
result 13
result 12
result 11
result 10
result 9
result 8
result 7
result 6
result 5
result 4
(n << i & 1 << 31) == 0
is an obscure way of writing
(n << i) >= 0
1 << 31 is the binary number 10000000 00000000 00000000 00000000. It's 1, shifted left 31 times.
X & 1 << 31 is a mask, checking if bit 31 is set to 1 in X.
Bit 31 in a signed 32-bit integer is the sign bit. So X & 1 << 31 == 0 is just checking if X is non-negative.
You said this finds the log to the base 2. But since you are working with integers it really only finds the log of the highest power of 2 <= n
An easier way (but not as interesting) is to simply do the following.
System.out.println(31-Integer.numberOfLeadingZeros(n));
I'm confused with bitwise operators. Whenever I do 99(0110 0011) << 2, the answer is 396. My understanding with left shifts is that add two 0s on the right side. So my answer would be 140(1000 1100) and not 396. Why is the answer 396 for 99 << 2 in Java?
You are only showing 8 bits, but an int is 32 bits.
byte 8 bits
short 16 bits
int 32 bits
long 64 bits
Integer calculations in Java are coerced to int or long, so even if your 99 value was a byte, the result of ((byte)99) << 2 is still an int.
0110 0011 = 99 (byte)
0000 0000 0000 0000 0000 0001 1000 1100 = 396 (int)
Now, you can always cast it back to a byte, which will discard all high-order bits:
(byte)(99 << 2) = (byte)0b10001100 = (byte)0x8C = -116
Or you can discard the high-order bits while keeping it an int:
(99 << 2) & 0xFF = 0b10001100 = 0x0000008C = 140
Because a Java int is a signed 32-bit quantity (not 8 bits) and a bitwise left shift by 2 (<< 2) is the same as * 4. You can see this like
int i = 99;
System.out.printf(" %s (%d)%n", Integer.toBinaryString(i), i);
i <<= 2;
System.out.printf("%s (%d)%n", Integer.toBinaryString(i), i);
Output is
1100011 (99)
110001100 (396)
I'm trying to learn bit shifting/masking. Here is my code:
int health = 511; // max 512, 9 bits
int aimAngle = 510; // max 512, 9 bits
int test = 511; // max 512, 9 bits
boolean bool = false; // max 1, 1 bit
int packed;
packed = health | aimAngle << 9 | test << 18 | (bool?1:0) << 19;
Debug.log("health: " + ((packed ) & 0b111111111));
Debug.log("aimAngle: " + ((packed >> 9) & 0b111111111));
Debug.log("test: " + ((packed >> 18) & 0b111111111));
Debug.log("bool: " + ((packed >> 19) & 0b1));
I'm getting all the values correctly except bool. It's always 1. What is wrong? Can't I shift zero to the beginning?
test is up to nine bits long. You shift it right 18 places. Therefore it occupies bits 18 to 27. You need to shift bool to place 28 to avoid it, not to place 19.
The 19th digit of packed is the second digit of test, which is a 1.
I have a small bug here somewhere in my code! I must be blind because i really can't seem to find it or figure it out. I have a list of byte arrays. I'm parsing out the first 2 elements as well as the very last element in each array. If i get the value -16, -11 or -7 i want to keep the values. For some reason, the last value in on of the arrays is not being deleted. Why is this happening?
Have you tried debugging it?
When you have b = -110
it passed this condition:
if(b!= -15 && i + 2 < srec.length() && (Character.digit(srec.charAt(i + 2), 16) << 4) + Character.digit(srec.charAt(i + 3), 16) != -15
&& (Character.digit(srec.charAt(i + 2), 16) << 4) + Character.digit(srec.charAt(i + 3), 16) != -11)
b != 15 -> true
i + 2 = 124 < srec.length() = 142 -> true
(Character.digit(srec.charAt(i + 2), 16) << 4)+ Character.digit(srec.charAt(i + 3), 16) = -7 and -7 != -15 and also -7 != -11
hence the data.add(b) is executed.