I'm preparing for an interview using the text, "Cracking the Coding Interview" by Gayle Laakman McDowell. On the section covering bit manipulation, there are two functions that are provided, but I don't quite understand how it works.
// To clear all bits from the most significant bit through i (inclusive), we do:
int clearMSBthroughI(int num, int i) {
int mask = (1 << i) - 1;
return num & mask;
}
// To clear all bits from i through 0 (inclusive), we do:
int clearBitsIthrough0(int num, int i) {
int mask = ~(((1 << (i+1)) - 1);
return num & mask;
}
In the first function, I understand what (1 << i) does of course, but what I'm not sure of is how subtracting 1 from this value affects the bits (i.e., (1 << i) - 1)).
I basically have the same confusion with the second function. To what effects, specifically on the bits, does subtracting 1 from ((1 << (i+1)) have? From my understanding, ((1 << (i+1)) results in a single "on" bit, shifted to the left i+1 times--what does subtracting this by 1 do?
Thanks and I hope this was clear! Please let me know if there are any other questions.
For those who by some chance have the text I'm referencing, it's on page 91 in the 5th Edition.
let's assume i= 5
(1 << i) give you 0100000 the 1 is placed in the 6th bit position
so now if we substract 1 from it, then we get 0011111 ==> only the 5 first bit are set to 1 and others are set to 0 and that's how we get our mask
Conclusion: for a giving i the (1 << i) -1 will give you a mask with the i first bits set to 1 and others set to 0
For the first question:
lets say i = 5
(1 << i ) = 0010 0000 = 32 in base 10
(1 << i ) -1 = 0001 1111 = 31
So a & with this mask clears the most significant bit down to i because all bit positions above and including index i will be 0 and any bellow will be 1.
For the second question:
Again lets say i = 5
(1 << (i + 1)) = 0100 0000 = 64 in base 10
(1 << (i + 1)) - 1 = 0011 1111 = 63
~((1 << (i + 1)) - 1) = 1100 0000 = 192
So a & with this masks clears bits up to index i
First Function:
Let's take i=3 for example. (1 << i) would yield 1000 in binary. Subtracting 1 from that gives you 0111 in binary (which is i number of 1's). ANDing that with the number will clear all but the last i bits, just like the function description says.
Second Function:
For the second function, the same applies. If i=3, then ((i << (i+1)) - 1) gives us 01111. The tilde inverts the bits, so we have 10000. It's important to do it this way instead of just shifting i bits left, because there could be any number of significant bits before our mask (so 10000 could be 8 bits long, and look like 11110000. That's what the tilde gets us, just to be clear). Then, the number is ANDed with the mask for the final result
// To clear all bits from the most significant bit through i (inclusive), we do:
int clearMSBthroughI(int num, int i) {
int mask = (1 << i) - 1;
return num & mask;
}
Take the example of i = 3
1<<3 gives you 0x00001000
(1<<3)-1 gives you 0x00000111
num & (1<<i)-1 will clear the bits from msb to i
// To clear all bits from i through 0 (inclusive), we do:
int clearBitsIthrough0(int num, int i) {
int mask = ~(((1 << (i+1)) - 1);
return num & mask;
}
same example of i = 3 gives you
1 <<(3+1) =0x00010000
1 <<(3+1)-1 = 0x00001111
mask =~(1<<(3+1)-1) = 0x11110000
num & mask will cleaR the bits from 0 throuh i
Related
I need a program that returns the number of trailing zeros in the binary rapresentation of a number. I found online a function written in C but I don't understand how it works
This is the function:
unsigned tzr(unsigned x)
{
unsigned n; /* number of bits */
n = 0;
if (!(x & 0x0000FFFF)) { n += 16; x >>= 16; }
if (!(x & 0x000000FF)) { n += 8; x >>= 8; }
if (!(x & 0x0000000F)) { n += 4; x >>= 4; }
if (!(x & 0x00000003)) { n += 2; x >>= 2; }
n += (x & 1) ^ 1; // anyway what does this do ?
return n;
}
Now I've really tried to understand how this works but I don't get it.
I really need someone who could explain it to me, I find this code very complicated.
And about those hexadecimal constants, these are their values:
0x0000FFFF = 65535
0x000000FF = 255
0x0000000F = 15
0x00000003 = 3
Now, why the program uses those values and makes a bitwise AND with the number?
Then I know that if you want to handle big numbers you must
use a while instead of the first if statement, like this:
while (!(x & 0x0000FFFF)) { bits += 16; x >>= 16; } // why should I need this ?
But I don't know why ! What's the difference about using a while instead of an if in this case?
The hexadecimal constants are AND'ed with the value to check whether the last [number] of digits is zero.0x0000FFFF is a number with 16 ones in binary. If the value AND'ed with 0x0000FFFF is equal to 0, you know that the last 16 digits are zeroes (the ifs check for the reverse of that statement). Going further 0x000000FF is a number with 8 ones in binary. The next check is for the last 8 digits, next for 4 digits and the last one for 2 digits as 0x00000003 is 11 in binary. After the checks the numbers are shifted to check whether further digits are also zero. This way we can check for any number of trailing zeroes as the values are powers of 2 and adding them works exactly like working with binary.
Last statement checks for the last digit after all the previous shifting is done - AND with 1 and checking if it's 0 or 1 with a XOR(^).
This program checks numbers with 32 bits. You can change the first if to a while to check larger, e.g. 64-bit, numbers. Another way is to check with 0xFFFFFFFF and then shift 32 bits at once.
The line n += (x & 1) ^ 1 checks the least significant bit (LSB) of the current state of x. If the LSB is a 1 then (x & 1) yeilds 1 which is then XORed (the caret symbol '^' means to XOR two values) with 1 to give 0 (1 ^ 1 == 0). When x has a 0 in the LSB and is XORed with 1 it yeilds 1 (0 ^ 1 == 1).
!(x&0x0000FFFF) will be true only when the last 16 bits of x are all 0's.
The & is a bitwise and, and 0x0000FFFFF is the number ending in 16 1's.
So the result of the and is 0 iff all 16 trailing bits are 0 (and so FALSE and 1 reverses the truth value) because if there is at least one 1 among the last 16, the and with the corresponding 1 in the constant will be 1. So then the and is not 0 (so TRUE and ! reverses the truth value).
So the code says: if the last 16 bits are 1, add 16 to n and throw the last 16 bits away (that is what x >>= 16 does).
The next line says in a similar way:
if the last 8 bits of the (possibly shortened x) are 0 ,add 8 to n and throw the rightmost 8 bits away, and so on for 4 and 2 bits as well
The last line adds 1 if the rightmost bit (x&1) is 0, otherwise 0 (1^1 = 0).
So say if the righmost 15 bits are 0, the first if will be false , n remains 0.
The second will be true, as we have more than 8. Tne new x will have 7 0-bits,
and n=8.
The third will also be true (we have still 4 or more), so the new x has 3 0-bits after the shift and n=12.
The fourth will also be true (2 or more 0's) so the new x has 1 0-bit and n=14.
The final statement adds 1, so get n=15.
Because we use decreasing powers of 2 we don't need a loop. We get all possible n values this way (except 32, for input x=0, a fully correct function should maybe check for that and early abort.
n += (x & 1) ^ 1; // anyway what does this do ?
This checks the right-most bit. Either it is set or NOT set.
If it is set, then there is NOT another 0 to add onto the running total of trailing zeros, so n+=0.
If it is NOT set, then there is another 0 to add onto the running total of trailing zeros, so n+=1.
Also, your example does NOT compile, it is missing two ; as follows:
unsigned tzr(unsigned x)
{
unsigned n; /* number of bits */
n = 0;
if (!(x & 0x0000FFFF)) { n += 16; x >>= 16; }
if (!(x & 0x000000FF)) { n += 8; x >>= 8; }
if (!(x & 0x0000000F)) { n += 4; x >>= 4 } // won't compile due to missing ;
if (!(x & 0x00000003)) { n += 2; x >>= 2 } // won't compile due to missing ;
n += (x & 1) ^ 1; // anyway what does this do ?
return n;
}
Also, you can always try printing out data, for example, every power of 2 has multiple trailing zeros, but only odd amounts of trailing zeros are incremented by an additional 1 from n += (x & 1) ^ 1;...
cout << tzr(9) << endl << endl; // 1001 (not a power of two )
cout << tzr(8) << endl << endl; // 1000 (8>>2 & 1)^1==1
cout << tzr(4) << endl << endl; // 0100 (4>>2 & 1)^1==0
cout << tzr(2) << endl << endl; // 0010 ( 2 & 1)^1==1
cout << tzr(1) << endl << endl; // 0001 ( 1 & 1)^1==0
tzr(9) == 0 ==> 0 + (9 & 1) ^ 1 == 0 + 0
tzr(8) == 3 ==> 2 + (8>>2 & 1) ^ 1 == 2 + 1
tzr(4) == 2 ==> 2 + (4>>2 & 1) ^ 1 == 2 + 0
tzr(2) == 1 ==> 0 + (2 & 1) ^ 1 == 0 + 1
tzr(1) == 0 ==> 0 + (1 & 1) ^ 1 == 0 + 0
Program ended with exit code: 0
You say, "I need a program that returns the number of trailing zeros in the binary rapresentation of a number." But does it have to be the program you found? Here's an alternative solution that implements tzr() in exactly one line of code,
#include <stdio.h>
#include <stdlib.h>
int tzr(int n) { /* --- every time n is even, add 1 and check n/2 --- */
return ( (n/2)*2 == n? 1+tzr(n/2) : 0 ); }
int main ( int argc, char *argv[] ) { /* --- test driver --- */
int n = (argc>1? atoi(argv[1]) : 1000);
printf("tzr(%d) = %d\n", n,tzr(n)); }
Is that any easier to understand?
(P.S. You could use bit masks and shifts instead of my divides and multiplies. That might be a little more efficient, but I thought my way might be a little more straightforward to read.)
Full disclosure, this is a homework problem and I do not need exact code. I am tasked with reproducing the following code while only using ~ & + <<.
int result = 0;
int i;
for(i = lowbit; i <= highbit; i++)
result |= 1 << i;
return result;
Where lowbit and highbit are parameters between 0 and 31 inclusive. If lowbit is a larger number than highbit, return 0.
What I have tried so for is the following code
int result = 0;
int negone = ~0x0;
int first = 1 << (lowbit + negone); //the first 1 bit is at the lowbit th location
int last = 1 << (highbit + negone); //the last 1 bit is at the highbit th location
int tick = ~(first + last); //attempting to get all bits in the range of low and highbit.
result = ~(~first & ~tick); //bitwise | without using |
result = ~(~last & ~result);
return result + 1; //the first bit should always be on.
So is there something fundamental I am missing here? In addition to what I have not working this also goes over my limit of 12 operators that I am allowed to use, but I'd like to try and get it working before I even begin to limit the operators.
When I run the test script on this I get errors on most of the tests it is put against including lowbit and highbit being equal to each other. Cases where highbit is the max size and lowbit is the least size seem to work though.
Any help would be much appreciated.
negone should be initialized this way:
uint32_t negone = ~0UL;
You are adding the bit number with a bit pattern in:
int first = 1 << (lowbit + negone); //the first 1 bit is at the lowbit th location
int last = 1 << (highbit + negone);
You should instead compute the 32 bit masks
uint32_t first = negone << lowbit; // all bits below lowbit are 0, others are 1
uint32_t last = negone << highbit << 1; // all bits above highbit are 1, other are 0
The result is obtained by masking the complement of first with last:
uint32_t result = ~first & last;
Combining the above steps gives is a direct solution with 7 operators (12 including the parentheses and the assignment), no addition, and no subtraction:
uint32_t result = ~(~0UL << highbit << 1) & (~0UL << lowbit);
I use 0UL because type unsigned long is guaranteed to have at least 32 bits, whereas type unsigned int might have just 16 bits.
1) Create a mask with the bits low to high set:
uint32_t mask = ~(~0ul << highbit << 1) & (~0ul << lowbit)
Example: lowbit = 4, highbit = 12 (9 bits)
mask = ~(0xffffffff << 12 << 1) & (0xffffffff << 4)
= ~(0xffff7000) & 0xfffffff0
= 0x00001fff & 0xfffffff0
= 0x00001ff0
2) Apply the mask to the value to be modified, this most simply an | operation, but that is not a valid operator in this exercise, so must be transformed using De Morgan's forum:
A|B -> ~(~A & ~B) :
result = ~(~result & ~mask) ;
It is of course possible to combining the two steps, but perhaps clarity would not then be served.
The original code generates a block of 1 from lowbit on until highbit (inclusive).
This can be achieved without a loop as follows:
int nrOfBits = highbit + ~lowbit + 2; // highbit - lowbit + 1
int shift = (nrOfBits & 0x1f + 1);
int result = ~(~(1 << shift)+1) << lowbit;
The idea is that, for example a range of 8 bits filled up with 1 means a number of 255, whereas 2^8 is 256. So - as operator - is not allowed, we use 2-complement to get -256, add 1 to get -255, and turn it back to +255 using 2-complement operator ~. Then, we just have to shift the block lowbits left.
The problem could be that tick = ~(first+last) does not flip the bit from the lowbit to the highbit.
Maybe we can do something like this:
/* supposed that lowbit = 1, highbit = 2 */
uint32_t negone = ~(0u); /* negone = all 1s */
uint32_t first = negone << lowbit; /* first = ...111110 */
uint32_t last = (1 << (highbit + 1)) + negone; /* last = ...0000111 */
uint32_t tick = last & first; /* tick = ...000110 */
result = ~(~result&~tick); /* Bitwise Or without | as you mentioned. */
It takes 11 bit operations to do this.
p.s. I am wondering why the first bit should be always on.
Edit: In order to avoid undefined operation, we should use unsigned type, like uint32_t.
I have do not have much knowledge of C and I'm stuck with a problem since one of my colleague is on leave.
I have a 32 bit number and i have to extract bits from it. I did go through a few threads but I'm still not clear how to do so. I would be highly obliged if someone can help me.
Here is an example of what I need to do:
Assume hex number = 0xD7448EAB.
In binary = 1101 0111 0100 0100 1000 1110 1010 1011.
I need to extract the 16 bits, and output that value. I want bits 10 through 25.
The lower 10 bits (Decimal) are ignored. i.e., 10 1010 1011 are ignored.
And the upper 6 bits (Overflow) are ignored. i.e. 1101 01 are ignored.
The remaining 16 bits of data needs to be the output which is 11 0100 0100 1000 11 (numbers in italics are needed as the output).
This was an example but I will keep getting different hex numbers all the time and I need to extract the same bits as I explained.
How do I solve this?
Thank you.
For this example you would output 1101 0001 0010 0011, which is 0xD123, or 53,539 decimal.
You need masks to get the bits you want. Masks are numbers that you can use to sift through bits in the manner you want (keep bits, delete/clear bits, modify numbers etc). What you need to know are the AND, OR, XOR, NOT, and shifting operations. For what you need, you'll only need a couple.
You know shifting: x << y moves bits from x *y positions to the left*.
How to get x bits set to 1 in order: (1 << x) - 1
How to get x bits set to 1, in order, starting from y to y + x: ((1 << x) -1) << y
The above is your mask for the bits you need. So for example if you want 16 bits of 0xD7448EAB, from 10 to 25, you'll need the above, for x = 16 and y = 10.
And now to get the bits you want, just AND your number 0xD7448EAB with the mask above and you'll get the masked 0xD7448EAB with only the bits you want. Later, if you want to go through each one, you'll need to shift your result by 10 to the right and process each bit at a time (at position 0).
The answer may be a bit longer, but it's better design than just hard coding with 0xff or whatever.
OK, here's how I wrote it:
#include <stdint.h>
#include <stdio.h>
main() {
uint32_t in = 0xd7448eab;
uint16_t out = 0;
out = in >> 10; // Shift right 10 bits
out &= 0xffff; // Only lower 16 bits
printf("%x\n",out);
}
The in >> 10 shifts the number right 10 bits; the & 0xffff discards all bits except the lower 16 bits.
I want bits 10 through 25.
You can do this:
unsigned int number = 0xD7448EAB;
unsigned int value = (number & 0x3FFFC00) >> 10;
Or this:
unsigned int number = 0xD7448EAB;
unsigned int value = (number >> 10) & 0xFFFF;
I combined the top 2 answers above to write a C program that extracts the bits for any range of bits (not just 10 through 25) of a 32-bit unsigned int. The way the function works is that it returns bits lo to hi (inclusive) of num.
#include <stdio.h>
#include <stdint.h>
unsigned extract(unsigned num, unsigned hi, unsigned lo) {
uint32_t range = (hi - lo + 1); //number of bits to be extracted
//shifting a number by the number of bits it has produces inconsistent
//results across machines so we need a special case for extract(num, 31, 0)
if(range == 32)
return num;
uint32_t result = 0;
//following the rule above, ((1 << x) - 1) << y) makes the mask:
uint32_t mask = ((1 << range) -1) << lo;
//AND num and mask to get only the bits in our range
result = num & mask;
result = result >> lo; //gets rid of trailing 0s
return result;
}
int main() {
unsigned int num = 0xd7448eab;
printf("0x%x\n", extract(num, 10, 25));
}
I have:
int8_t byteFlag;
and I want to get the first bit of it? I think I probably need to use & and >> but not sure how exactly. Any help?
int func(int8_t byteFlag, int whichBit)
{
if (whichBit > 0 && whichBit <= 8)
return (byteFlag & (1<<(whichBit-1)));
else
return 0;
}
Now func(byteFlag, 1) will return 1'st bit from LSB. You can pass 8 as whichBit to get 8th bit (MSB).
<< is a left shift operant. It will shift the value 1 to the appropriate place and then we have to do & operation to get value of that particual bit in byteFlag.
for func(75, 4)
75 -> 0100 1011
1 -> 0000 0001
1 << (4-1) -> 0000 1000 //means 3 times shifting left
75 & (1 << (4 - 1)) will give us 1.
You would use the & operator.
If by "first bit" you mean LSB:
int firstBit = byteFlag & 1;
If by "first bit" you mean MSB:
int firstBit = byteFlag >> (sizeof(byteFlag) * 8 - 1);
Just mask the high bit
int8_t high_bit = byteFlag & (1 << 7); //either 1 or 0
Another trick since this is a signed int
if (byteFlag < 0) firstBitSet = true;
The last one works because of the representation of numbers in two's complement. The high bit is set if the number is negative.
int8_t bit_value = (byteFlag & (1U << bitPosition)) ? 1 : 0 ;
/* now it's up to you to decide which bit is the "first".
bitPosition = 0 is the minor bit. */
The solution is given below. To get first bit of number, set bit = 1;
int bitvalue(int8_t num, int bit)
{
if (bit > 0 && bit <= 8)
return ( (num >> (bit-1)) & 1 );
else
return 0;
}
Let's say I have a byte with six unknown values:
???1?0??
and I want to swap bits 2 and 4 (without changing any of the ? values):
???0?1??
But how would I do this in one operation in C?
I'm performing this operation thousands of times per second on a microcontroller so performance is the top priority.
It would be fine to "toggle" these bits. Even though this is not the same as swapping the bits, toggling would work fine for my purposes.
Try:
x ^= 0x14;
That toggles both bits. It's a little bit unclear in question as you first mention swap and then give a toggle example. Anyway, to swap the bits:
x = precomputed_lookup [x];
where precomputed_lookup is a 256 byte array, could be the fastest way, it depends on the memory speed relative to the processor speed. Otherwise, it's:
x = (x & ~0x14) | ((x & 0x10) >> 2) | ((x & 0x04) << 2);
EDIT: Some more information about toggling bits.
When you xor (^) two integer values together, the xor is performed at the bit level, like this:
for each (bit in value 1 and value 2)
result bit = value 1 bit xor value 2 bit
so that bit 0 of the first value is xor'ed with bit 0 of the second value, bit 1 with bit 1 and so on. The xor operation doesn't affect the other bits in the value. In effect, it's a parallel bit xor on many bits.
Looking at the truth table for xor, you will see that xor'ing a bit with the value '1' effectively toggles the bit.
a b a^b
0 0 0
0 1 1
1 0 1
1 1 0
So, to toggle bits 1 and 3, write a binary number with a one where you want the bit to toggle and a zero where you want to leave the value unchanged:
00001010
convert to hex: 0x0a. You can toggle as many bits as you want:
0x39 = 00111001
will toggle bits 0, 3, 4 and 5
You cannot "swap" two bits (i.e. the bits change places, not value) in a single instruction using bit-fiddling.
The optimum approach if you want to really swap them is probably a lookup table. This holds true for many 'awkward' transformations.
BYTE lookup[256] = {/* left this to your imagination */};
for (/*all my data values */)
newValue = lookup[oldValue];
The following method is NOT a single C instruction, it's just another bit fiddling method. The method was simplified from Swapping individual bits with XOR.
As stated in Roddy's answer, a lookup table would be best. I only suggest this in case you didn't want to use one. This will indeed swap bits also, not just toggle (that is, whatever is in bit 2 will be in 4 and vice versa).
b: your original value - ???1?0?? for instance
x: just a temp
r: the result
x = ((b >> 2) ^ (b >> 4)) & 0x01
r = b ^ ((x << 2) | (x << 4))
Quick explanation: get the two bits you want to look at and XOR them, store the value to x. By shifting this value back to bits 2 and 4 (and OR'ing together) you get a mask that when XORed back with b will swap your two original bits. The table below shows all possible cases.
bit2: 0 1 0 1
bit4: 0 0 1 1
x : 0 1 1 0 <-- Low bit of x only in this case
r2 : 0 0 1 1
r4 : 0 1 0 1
I did not fully test this, but for the few cases I tried quickly it seemed to work.
This might not be optimized, but it should work:
unsigned char bit_swap(unsigned char n, unsigned char pos1, unsigned char pos2)
{
unsigned char mask1 = 0x01 << pos1;
unsigned char mask2 = 0x01 << pos2;
if ( !((n & mask1) != (n & mask2)) )
n ^= (mask1 | mask2);
return n;
}
The function below will swap bits 2 and 4. You can use this to precompute a lookup table, if necessary (so that swapping becomes a single operation):
unsigned char swap24(unsigned char bytein) {
unsigned char mask2 = ( bytein & 0x04 ) << 2;
unsigned char mask4 = ( bytein & 0x10 ) >> 2;
unsigned char mask = mask2 | mask4 ;
return ( bytein & 0xeb ) | mask;
}
I wrote each operation on a separate line to make it clearer.
void swap_bits(uint32_t& n, int a, int b) {
bool r = (n & (1 << a)) != 0;
bool s = (n & (1 << b)) != 0;
if(r != s) {
if(r) {
n |= (1 << b);
n &= ~(1 << a);
}
else {
n &= ~(1 << b);
n |= (1 << a);
}
}
}
n is the integer you want to be swapped in, a and b are the positions (indexes) of the bits you want to be swapped, counting from the less significant bit and starting from zero.
Using your example (n = ???1?0??), you'd call the function as follows:
swap_bits(n, 2, 4);
Rationale: you only need to swap the bits if they are different (that's why r != s). In this case, one of them is 1 and the other is 0. After that, just notice you want to do exactly one bit set operation and one bit clear operation.
Say your value is x i.e, x=???1?0??
The two bits can be toggled by this operation:
x = x ^ ((1<<2) | (1<<4));
#include<stdio.h>
void printb(char x) {
int i;
for(i =7;i>=0;i--)
printf("%d",(1 & (x >> i)));
printf("\n");
}
int swapb(char c, int p, int q) {
if( !((c & (1 << p)) >> p) ^ ((c & (1 << q)) >> q) )
printf("bits are not same will not be swaped\n");
else {
c = c ^ (1 << p);
c = c ^ (1 << q);
}
return c;
}
int main()
{
char c = 10;
printb(c);
c = swapb(c, 3, 1);
printb(c);
return 0;
}