Help to begin in assigning specific bits - c

So I have a problem for my class that I am having trouble getting started on. I am not asking people to do the problem for me, I just would like any nudge in the right direction. I need to create a function in C that when given any 32 bit integer it returns an integer where every 4th bit is set to a 1 starting at the least sig bit. I understand what it is supposed to look like in the end, but getting started I am lost on. We are not allowed to use any for loops or conditionals, just the standard bitwise and logical operators(! ~ & ^ | + << >>). Once again, I am not asking anyone to do this for me, I just would like some help in getting me thinking on the right track. I have seen some of the other posts on here and on other pages, but none seem to click. I understand that you can bitshift a 1 into a certain place x<<3 but going beyond that I am stuck. Any help would be appreciated.

int get_int_with_every_fourth_bit_set()
{
return 0x88888888;
}
Ok, that was mostly facetious. Here's a list of what the bitwise operators do:
bitwise NOT (~): Toggle a bit, 0 to 1 and 1 to 0
AND (&): Set a bit if the bit in that position is set in both operands
OR (|): Set a bit if the bit in that position is set in either operand
XOR (^): Set a bit if exactly one bit in that position is set between the two operands
Bitwise shift (<< and >>): Move each bit over the specified amount in the given direction. When shifting left, zeros are added to the least significant bit. When shifting right, a zero will be added if the value is either unsigned or positive.
Here are some bitwise tricks that are good to know:
A bitwise shift left by one is the same as multiplying by two. A bitwise shift right by one is the same as dividing by two, and rounding down.
All powers of two have exactly one 1 bit. To see if a number is a power of two, you can do this:
return !(x & (x - 1)) && x
As an example, say x = 16, which is a power of two. Then, x - 1 = 15, so the values to be ANDed are 00010000 and 00001111. Since each bit position has a zero in at least one of the two operands, the result is zero. !0 is true, so check to see if x != 0. Since 16 != 0, the statement returns true. If you try it with a number that is not a power of two and not zero, then the x & (x - 1) check will always be true. So cool!
Another tip: since 0 ^ 0 = 0 and 1 ^ 1 = 0, you can use XOR to see what bits have changes. For example, if you have two bytes and want to see the bits that changed between then, the XOR of the two bytes will give you a 1 in the position of all bits that have changed.

Can you write down (in hex) the 32 bit integer that has every 4th bit set to 1, and all other bits set to 0?
Now, is there an operation you can apply to your input and this magic number, which sets every 4th bit of the input to 1, but leaves the other bits alone?

Check out bitmasking.
...Therefore, to make sure a bit is on, OR can be used with a 1. To leave a bit unchanged, OR is used with a 0.
So the mask for your case (leaving other bits unchanged) would be:
Binary: 10001000100010001000100010001000
Hex: 88888888

Related

Finding if a value falls within a range, using bitwise operators in C

So i am working on this method, but am restricted to using ONLY these operators:
<<, >>, !, ~, &, ^, |, +
I need to find if a given int parameter can be represented using 2's complement arithmetic in a given amount of bits.
Here is what I have so far:
int validRange(int val, int bits){
int minInRange = ~(1<<(bits + ~0 ))+1; //the smallest 2's comp value possible with this many bits
int maxInRange = (1<<(bits+~0))+~0; //largest 2's comp value possible
..........
}
This is what I have so far, and all I need to do now is figure out how to tell if minInRange <= val <=maxInRange. I wish I could use the greater than or less than operator, but we are not allowed. What is the bitwise way to check this?
Thanks for any help!
Two's complement negative numbers always have a '1' in their high bit.
You can convert from negative to positive (and vice versa) by converting from FF -> 00 -> 01. That is, invert the bits, add 1. (01 -> FE -> FF also works: invert the bits, add 1)
A positive number can be represented if the highest set bit in the number is within your range. (nbits - 1: 7 bits for an 8 bit signed char, etc.)
I'm not sure if your constraints allow you to use arrays. They would speed up some things but can be replaced with loops or if statements.
Anyway, if 1 << (NUM_INT_BITS-1) is set on your input, then it's negative.
Invert, add one.
Now, consider 0. Zero is a constant, and it's always the same no matter how many bits. But if you invert 0, you get "all the bits" which changes by architecture. So, ALL_BITS = ~0.
If you want to know if a positive number can be represented in 2 bits, check to see if any bits greater than or equal to bit 2 are set. Example:
two_bits = 0b00000011
any_other_bits = ~two_bits # Result: 0b11...11100
if positive_number & any_other_bits
this number is too fat for these bits!
But how do you know what ~two_bits should be? Well, it's "all set bits except the bottom however-many". And you can construct that by starting with "all set bits" and shifting them upwards (aka, "left") however-many places:
any_other_bits = ~0 << 2 # where "2" is the number of bits to check
All together now:
if (val & ((unsigned)INT_MAX + 1))
val = ~val + 1;
mask = ~0 << bits;
too_wide = val & mask;
return !too_wide;
To test if a number can be represented in a N-bit 2s compliment number: Simply test that either
The number bitwise-and'ed with the compliment of a word with the low (N-1) bits set is equal to zero
OR The high InputBitWidth-(N-1) bits of the number are 1s.
mask=(1<<(bits-1))-1; return ( !(val&mask) | !((val&~mask)^~mask) );

How to zero out bottom n bits in a C unsigned int?

I am trying to write my own C floor function. I am stuck on this code detail. I would just like to know how I can zero out the bottom n bits of an unsigned int.
For example, to round 51.5 to 51.0, I need to zero out the bottom 18 bits, and keep the top 14. Since it's a floor function, I want to make a mask to zero out the bottom (23 minus exponent) bits from the float representation. I know how to make a mask for individual cases like that, but I'm not sure how to code it so that it will work for all. Please help.
A much simpler way is doing just this:
value = (value >> bits) << bits
because the shift left will fill it in with zeroes, not whatever was in there.
Shift a number left N bits. Subtract one. Invert the bits. And with the number you need to mask.
1 << 14 = 00000000000000000010000000000000
-1 = 00000000000000000001111111111111
~ = 11111111111111111110000000000000
When you and with this, a 1 in the mask will preserve the input, and 0 in the mask will set the result to 0.

Next set of n elements in set using bitwise operators

Reading the book "C - A reference manual (Fifth Edition)", I stumbled upon this piece of code (each integer in the SET is represented by a bit position):
typedef unsigned int SET;
#define emptyset ((SET) 0)
#define first_set_of_n_elements(n) (SET)((1<<(n))-1)
/* next_set_of_n_elements(s): Given a set of n elements,
produce a new set of n elements. If you start with the
result of first_set_of_n_elements(k)/ and then at each
step apply next_set_of_n_elements to the previous result,
and keep going until a set is obtained containing m as a
member, you will have obtained a set representing all
possible ways of choosing k things from m things. */
SET next_set_of_n_elements(SET x) {
/* This code exploits many unusual properties of unsigned arithmetic. As an illustration:
if x == 001011001111000, then
smallest == 000000000001000
ripple == 001011010000000
new_smallest == 000000010000000
ones == 000000000000111
returned value == 001011010000111
The overall idea is that you find the rightmost
contiguous group of 1-bits. Of that group, you slide the
leftmost 1-bit to the left one place, and slide all the
others back to the extreme right.
(This code was adapted from HAKMEM.) */
SET smallest, ripple, new_smallest, ones;
if (x == emptyset) return x;
smallest = (x & -x);
ripple = x + smallest;
new_smallest = (ripple & -ripple);
ones = ((new_smallest / smallest) >> 1) -1;
return (ripple | ones);
}
I'm lost at the calculation of 'ones', and it's significance in the calculation. Although I can understand the calculation mathematically, I cannot understand why this works, or how.
On a related note, the authors of the book claim that the calculation for first_set_of_n_elements "exploits the properties of unsigned subtractions". How is (2^n)-1 an "exploit"?
The smallest computation gets the first non-0 bit of your int. How does it works ?
Let n be the bit length of your int. The opposite of a number x (bits bn-1...b0) is computed in a way that when you sum x to -x, you will get 2n. Since your integer is only n-bit long, the resulting bit is discarded and you obtain 0.
Now, let b'n-1...b'0 be the binary representation of -x.
Since x+(-x) must be equal to 2n, when you meet the first bit 1 of x (say at position i), the related -x bit will also be set to 1 and when adding the numbers, you'll get a carry.
To obtain the 2n, this carry must propagate through all the bits until the end of the bit sequence of your int. Thus, the bit of -x at each position j with i < j < n follows the properties below :
bj + b'j + 1 = 10(binary)
Then, from the above we can infer that :
bj = NOT(b'j) and thus, that bj & b'j = 0
On the other hand, the bits b'j of -x located at a position j such that 0 <= j < i are ruled by what follows :
bj + b'j = 0 or 10
Since all the related bj are set to 0, the only option is b'j = 0
Thus, the only bit that is 1 in both x and -x is the one at position i
In your example :
x = 001011001111000
-x = 110100110001000
Thus,
0.0.1.0.1.1.0.0.1.1.1.1.0.0.0
1.1.0.1.0.0.1.1.0.0.0.1.0.0.0 AND
\=====================/
0.0.0.0.0.0.0.0.0.0.1.0.0.0
The ripple then turns every contiguous "1" after position i (bit i included) to 0, and the first following 0 bit to 1 (due to the carry propagation). That's why you ripple is :
r(x) = 0.0.1.0.1.1.0.1.0.0.0.0.0.0.0
Ones is computed as the division of smallest(r(x)) over smallest(x). Since smallest(x) is an integer with only a single bit set to 1 at position i, you have :
(smallest(r(x)) / smallest(x)) >> 1 = smallest(r(x)) >>(i+1)
The resulting integer has also only one bit set to 1, at say index p, thus, substract -1 to this value will get you an integer ones such that :
For each j such that 0 <= j < p,
onesj = 1
For each j such that p <= j < n,
onesj = 0
Finally, the return value is the integer such that :
The first subsequence of 1-bit of the argument is set to 0.
All the 0-bit before the subsequence are set to 1.
The first 0-bit after the subsequence is set to 1.
The remaining bits are left unchanged
Then, I can't explain the remaining part since I did not understand the sentence :
a set is obtained containing m as a member
First of all, this code is rather obscure and doesn't look like anything worth spending time pondering upon, it will only yield useless knowledge.
The "exploit" is that the code relies on implementation-defined behavior of various arithmetric rules.
001 0110 0111 1000 is a 15-bit number. Why the author uses 15 bit numbers instead of 16, I
don't know. Seems like a typo remaining even after 5 editions.
If we put a minus sign in front of that binary number on a two's complement system (explanation of two's complement here), it will turn into 1110 1001 1000 1000. Because the compiler will preserve the decimal presentation of the number (5752) and translate it to its negative equivalent (-5752). (However, the actual data type will remain unsigned int, so if you tried to print it you would get the garbage number 59784.)
0001 0110 0111 1000
AND 1110 1001 1000 1000
= 0000 0000 0000 1000
The C standard does not enforce two's complement, so the code in that book is not portable.
It's a little misleading, because it actually exploits 2's complement. First, the calculation of smallest:
In 2's complement representation, for the x in the comments -x is 110100110001000. Focus on the least significant bit of x that is a one; since two's complement is essentially 1's complement plus 1, that bit will be set in both x and -x and no other bit position after it (on the way to the LSB) will have that property. That's how you get the smallest bit set.
ripple is pretty straightforward and is named as such because it propagates ones to the MSB, and smallest_ripple follows from the description above.
ones is the number we should add to the ripple in order to continue choosing n elements, picture it below:
ones: 11 next set: 100011
ones: 1 next set: 100101
ones: 0 next set: 100110
Running it will indeed show you all the ways of choosing n bits out of CHAR_BIT * sizeof(int) - 1 items (CHAR_BIT * sizeof(int) bits are needed because -x of an n-bit number needs at worst n+1 bits to be represented).
First, here a exemple of the output we can get with n=4. The idea is that we start with 'n' LSB set to '1', and then we iterate through all the combinations of numbers with the same count of bits set to '1':
1111
10111
11011
11101
11110
100111
101011
101101
101110 (*)
110011
110101
110110
111001
111010
111100
1000111
1001011
1001101
It is working the following way. I will use the number with the star above as an exemple:
101110
We get the LSB set to '1' as clearly explained in other answers.
101110
& 010011
= 000010
We "move" the LSB one position to the left by adding it to the original number. If the bit immediately on the left is '0', this is easy to understand, as the subsequent operations will do nothing. If this left bit is '1', we get a carry which will propagate to the left. The problem with this last case is that the numbers of '1' will change, so we have to set back some '1' to keep their count constant.
101110
+ 000010
= 110000
To do so, we retrieve the LSB of the new result, and by dividing it with the previous LSB, we get the number of bits over which the carry has propagated. This is converted to plain '1' at the lowest positions with the '-1',
010000
/ 000010
= 001000
>> 1
- 1
= 000011
We finally OR the result of the addition and the ones.
110011
I would say that the "exploit" is on the unsigned change of sign, in the operation (x & -x).

How does this method count the number of 1s in binary representation? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
n & (n-1) what does this expression do?
Consider the following algorithm:
int count(int num)
{
int ones = 0;
while(num)
{
++ones;
num &= num - 1;
}
return ones;
}
What is the significance of num & (num-1)? How does it work?
num &= num - 1;
clears the least significant bit set in num.
This algorithm counts the bits set by clearing them and incrementing a counter until they're all gone.
To understand why it clears the least significant bit, you need to think about what decrementing does to the bits and of course understand what the & operation does.
Subtracting in binary works just as the process we were all taught in decimal as children.
You work from right (least significant) to left, simply subtracting individual digits when possible, and "borrowing" from the next digit when necessary.
When subtracting 1 from a binary number ending in a set of zeros, this "borrowing" and subtracting turns all the zeros in lower positions than the rightmost 1 to 1's and turns the rightmost 1 to a zero (because it was borrowed).
Then applying the & operator leaves all the lesser digits zero because they're zero in num, and sets the least significant bit of num to zero because it's zero in num-1.
Both of these operations leave the more significant digits unchanged.
Here's a good list of bit twiddling hacks including this one, which is due to Brian Kernighan.
Here's a more detailed (but not very well written!) answer.
There are two cases: either the least significant bit is set, then "num-1" unsets it. Or it's not set, then num-1 turns all trailing zeroes into 1, and the least significant 1 to a 0, the rest of the bits are not changed. When you "and", all unchanged bits are the same, the least significant 1 which is anded with a 0 turns into a 0 and the others remaining bits are zeroes. This is illustrated here:
num = 1000110111[1]0000
num - 1 = 1000110111[0]1111
num & (num - 1) = 1000110111[0]0000
I would point out that there is often an assembly operation to count the number of ones in a single cycle. The operation is called "popcount" and for instance in GCC, it can be accessed using "__builtin_popcount", see this link for details.
The algorithm operates like pump, moving bits effectively to right in the "num" variable. The line
num &= num - 1;
is where the work is done, there's an assignment and boolean AND operation going on at the same time. It's all about bit arithmetic.
Pom

What does >> and 0xfffffff8 mean?

I was told that (i >> 3) is faster than (i/8) but I can't find any information on what >> is. Can anyone point me to a link that explains it?
The same person told me "int k = i/8, followed by k*8 is better accomplished by (i&0xfffffff8);" but again Google didn't help m...
Thanks for any links!
As explained here the >> operator is simply a bitwise shift of the bits of i. So shifting i 1 bit to the right results in an integer-division by 2 and shifting by 3 bits results in a division by 2^3=8.
But nowadays this optimization for division by a power of two should not really be done anymore, as compilers should be smart enough to do this themselves.
Similarly a bitwise AND with 0xFFFFFFF8 (1...1000, last 3 bits 0) is equal to rounding down i to the nearest multiple of 8 (like (i/8)*8 does), as it will zero the last 3 bits of i.
Bitwise shift right.
i >> 3 moves the i integer 3 places to the right [binary-way] - aka, divide by 2^3.
int x = i / 8 * 8:
1) i / 8, can be replaced with i >> 3 - bitwise shift to the right on to 3 digits (8 = 2^3)
2) i & xfffffff8 comparison with mask
For example you have:
i = 11111111
k (i/8) would be: 00011111
x (k * 8) would be: 11111000
Therefore the operation just resets last 3 bits:
And comparable time cost multiplication and division operation can be rewritten simple with
i & xfffffff8 - comparison with (... 11111000 mask)
They are Bitwise Operations
The >> operator is the bit shift operator. It takes the bit represented by the value and shifts them over a set number of slots to the right.
Regarding the first half:
>> is a bit-wise shift to the right.
So shifting a numeric value 3 bits to the right is the same as dividing by 8 and inting the result.
Here's a good reference for operators and their precedence: http://web.cs.mun.ca/~michael/c/op.html
The second part of your question involves the & operator, which is a bit-wise AND. The example is ANDing i and a number that leaves all bits set except for the 3 least significant ones. That is essentially the same thing happening when you have a number, divide it by 8, store the result as an integer, then multiply that result by 8.
The reason this is so is that dividing by 8 and storing as an integer is the same as bit-shifting to the right 3 places, and multiplying by 8 and storing the result in an int is the same as bit-shifting to the left 3 places.
So, if you're multiplying or dividing by a power of 2, such as 8, and you're going to accept the truncating of bits that happens when you store that result in an int, bit-shifting is faster, operationally. This is because the processor can skip the multiply/divide algorithm and just go straight to shifting bits, which involves few steps.
Bitwise shifting.
Suppose I have an 8 -bit integer, in binary
01000000
If I left shift (>> operator) 1 the result is
00100000
If I then right shift (<< operator) 1, I clearly get back to wear I started
01000000
It turns out that because the first binary integer is equivelant to
0*2^7 + 1*2^6 + 0*2^5 + 0*2^4 + 0*2^3 + 1*2^2 + 0*2^1 + 0*2^0
or simply 2^6 or 64
When we right shift 1 we get the following
0*2^7 + 0*2^6 + 1*2^5 + 0*2^4 + 0*2^3 + 1*2^2 + 0*2^1 + 0*2^0
or simply 2^5 or 32
Which means
i >> 1
is the same as
i / 2
If we shift once more (i >> 2), we effectively divide by 2 once again and get
i / 2 / 2
Which is really
i / 4
Not quite a mathematical proof, but you can see the following holds true
i >> n == i / (2^n)
That's called bit shifting, it's an operation on bits, for example, if you have a number on a binary base, let's say 8, it will be 1000, so
x = 1000;
y = x >> 1; //y = 100 = 4
z = x >> 3; //z = 1
Your shifting the bits in binary so for example:
1000 == 8
0100 == 4 (>> 1)
0010 == 2 (>> 2)
0001 == 1 (>> 3)
Being as you're using a base two system, you can take advantage with certain divisors (integers only!) and just bit-shift. On top of that, I believe most compilers know this and will do this for you.
As for the second part:
(i&0xfffffff8);
Say i = 16
0x00000010 & 0xfffffff8 == 16
(16 / 8) * 8 == 16
Again taking advantage of logical operators on binary. Investigate how logical operators work on binary a bit more for really clear understanding of what is going on at the bit level (and how to read hex).
>> is right shift operation.
If you have a number 8, which is represented in binary as 00001000, shifting bits to the right by 3 positions will give you 00000001, which is decimal 1. This is equivalent to dividing by 2 three times.
Division and multiplication by the same number means that you set some bits at the right to zero. The same can be done if you apply a mask. Say, 0xF8 is 11111000 bitwise and if you AND it to a number, it will set its last three bits to zero, and other bits will be left as they are. E.g., 10 & 0xF8 would be 00001010 & 11111000, which equals 00001000, or 8 in decimal.
Of course if you use 32-bit variables, you should have a mask fitting this size, so it will have all the bits set to 1, except for the three bits at the right, giving you your number - 0xFFffFFf8.
>> shifts the number to the right. Consider a binary number 0001000 which represents 8 in the decimal notation. Shifting it 3 bits to the right would give 0000001 which is the number 1 in decimal notation. Thus you see that every 1 bit shift to the right is in fact a division by 2. Note here that the operator truncates the float part of the result.
Therefore i >> n implies i/2^n.
This might be fast depending on the implementation of the compiler. But it generally takes place right in the registers and therefore is very fast as compared to traditional divide and multiply.
The answer to the second part is contained in the first one itself. Since division also truncates all the float part of the result, the division by 8 will in theory shift your number 3 bits to the right, thereby losing all the information about the rightmost 3 bits. Now when you again multiply it by 8 (which in theory means shifting left by 3 bits), you are padding the righmost 3 bits by zero after shifting the result left by 3 bits. Therefore, the complete operation can be considered as one "&" operation with 0xfffffff8 which means that the number has all bits 1 except the rightmost 4 bits which are 1000.

Resources