Hi all, Sorry if this sounds so noob, but I never worked in shift or bitwise operators in my code, like ever. But I do understand basic stuff about them.
So recently I had stumbled upon a code, which will get all shift timing from user, and arrange them nicely for displaying. So what I would like to know is, how these particular code blocks work. (Marked with "This Code"). After looking at this, I checked out Calendar class in java, and even they used it in many places. Now I am curious to understand and learn more about this!
int[] hours = new int[7];
static final String[] namesOfDays = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
public void addNewShift(final int startTime, final int endTime, int[] days) {
for (int i = startTime; i <= endTime; i++) {
This code=> for (int d : days) hours[d] |= (1 << i);
}
}
public void displayHours() {
final StringBuilder sb = new StringBuilder();
String prevDay = getDayForInt(hours[0]);
String startDay = namesOfDays[0];
String endDay = namesOfDays[0];
for (int i = 1; i < hours.length; i++) {
final String day = getDayForInt(hours[i]);
if (day.equals(prevDay)) endDay = namesOfDays[i];
else {
appendDayString(sb, startDay, endDay, prevDay);
prevDay = day;
startDay = endDay = namesOfDays[i];
}
}
appendDayString(sb, startDay, endDay, prevDay);
System.out.println(sb.toString());
}
String getDay(final int shiftVal) {
final StringBuilder sb = new StringBuilder();
int startHour = -1, endHour = -1;
for (int i = 0; i <= 24; i++) {
This code=> if (((1 << i) & shiftVal) > 0) {
if (startHour == -1) startHour = i;
endHour = i;
} else if (startHour >= 0) {
sb.append("\t" + hourFormat(startHour) + " to " + hourFormat(endHour) + "\n");
startHour = endHour = -1;
}
}
if (startHour >= 0) sb.append("\t" + hourFormat(startHour) + " to " + hourFormat(endHour) + "\n");
return sb.toString();
}
The higlighted part is what's bugging me. It would be of great help if you guys can explain this to me, so I guess I can use them in some other cases!
Gist of the complete code : gist.github.com/rajkumarpb/94030e029e351f4562d234…
As i understand condition
shiftval = 00001010;
startHour = -1;
endHour = -1;
iteration 1:
i = 00000000;
1 = 00000001;
0000001 = 00000001 << 0; which just means shift the 1 by zero positions to the left
0000000 = 00000001 & 00001010; this should be obvious boolean algebra
iteration 2:
i = 00000001;
1 = 00000001;
0000010 = 00000001 << 1;
0000010 = 00000010 & 00001010
first condition is true:
startHour = 0000010; // 2
endHour = 0000010; // 2
iteration3:
i = 00000010;
1 = 00000001;
0000100 = 00000001 << 2;
0000000 = 00000100 & 00001010;
second condition is true:
string buffer : "2 to 2"
startHour = -1;
endHour = -1;
iteration4:
i = 00000011;
1 = 00000001;
0001000 = 00000001 << 3;
0001000 = 00001000 & 00001010;
first condition is true:
startHour = 3;
endHour = 3;
iteration5:
i = 00000100;
1 = 00000001;
0010000 = 00000001 << 4;
0000000 = 00001000 & 00001010;
second condition is true:
stringBuffer : "4 to 4";
so what I deduce is that, this is a rather elegant mechanism to calculate ranges :)
shiftval = 00001111;
startHour = -1;
endHour = -1;
iteration1:
i = 00000000;
1 = 00000001;
0000001 = 00000001 << 0;
0000001 = 00000001 & 00001111;
first condition is true:
startHour = 1;
endHour = 1;
iteration2:
i = 00000001;
1 = 00000001;
0000010 = 00000001 << 1;
0000010 = 00000010 & 00001111;
first condition is true:
startHour = 1;
endHour = 2;
iteration3:
i = 00000010;
1 = 00000001;
0000100 = 00000001 << 2;
0000100 = 00000100 & 00001111;
first condition is true:
startHour = 1;
endHour = 3;
iteration4:
i = 00000011;
1 = 0000001;
0001000 = 00000001 << 3;
0001000 = 00001000 & 00001111;
first condition is true:
startHour = 1;
endHour = 4;
iteration5:
....
second condition is true:
stringBuffer : "1 to 4";
startHour = -1;
endHour = -1;
that's rather elegant :D I don't know if the behaviour is correct and what you need but the intention is nice :D
Lets see, The hours array looks like taken/free hours in a day (length of 7)
How do you know if the hour at day x is taken?
Check the bit values in hours[x] If the 3rd bit is on - the 3rd hour is taken
Lets take for example the following array [9,0,0,2,0,0,0] Sundays value is 9 which means it's bits look like 1001 => the 1st hour is taken and the 4th. Wednesdays value is 2 which means its 2nd hour is taken. All other days are free
Now lets take a look at the code
AddNewShift: It "activates" all the hours from startTime => endTime in the given days array. How? |= Lets look at an example X |= 1 means that what ever x contains i want that the first bit will be activated Its like X = X | 1 | means the OR bitwise operation
So in our code hours[d] |= some int Means to activate 'some int' hours in 'd' day
For example If our hours array will be [0,0,0,0,0,0,0] And the day array will be [0,1] For hours[d] |= 3 Will get [3,3,0,0,0,0,0] We activated hours 1,2 in the 1st,2nd days
1 << i If im not mistaken means to shift left 1 i times So 1 << 3 will be the number 8 We moved it 3 bits left In the function we do that for each hour from startTime until endTime, why? We want to "activate" that hour in all the given days
Unfortunately i ran out of time to explain the second function..
It's very hard to read this code example since many parts are missed, very wrong tabulation and coding style, 0 comments. I would also recommend to use // or /* */ comments and put your "THIS CODE" there so it could be found instantly, otherwise I had to search in browser. I believe appendDayString function and public in last function is also missing.
Always put DOC-comments above each function describing what exactly function and each param does does, each param itself and return value. In case of Java there is Javadoc
Could you provide:
And a use-case example where you have data X and result Y.
First one gives your an array of 7 days with bits in them, each bit represents an hours in the day.
So if you're working only 0am, it'll look like this for that specific day:
000000000000000000000001Converted to decimal, it's1Shift left one and it becomes:
000000000000000000000010000000000000000000000010OR000000000000000000000001=000000000000000000000011If you're working 0am to 5am, it'll look like this:
000000000000000000111111Converted to decimal, it's63So if you're working 3 days of the week from 0am to 5am, it'll look like this:
[0, 0, 0, 63, 63, 63, 0]Bit shifting is a convenient way to package data inside an integer in a very a efficient manner.
The second one checks if that shift is taken by seeing if bits clash when and-ing them, bits that are the same when doing a bitwise
andbecomes1and all other bits become0. So in this example shift 23h is already taken:010000000000000000000010AND010000000000000000000000=010000000000000000000000So in other words, to check if shift 23h is taken, simply AND the person's shift-roster with
2^23or010000000000000000000000b and if you get back exactly2^23, it's taken, otherwise if you get back0, it's available.These binary numbers are effectively powers of two, 0h would be 2^0, 23h would be 2^23
Hope it helps.