Dear all C programmer:
X = 1 << N; (left shift)
how to recover N from X ?
Thanks
N in this case is the bit position where you shifted in a 1 at. Assuming that X here only got one bit set. Then to find out what number that bit position corresponds to, you have to iterate through the data and mask with bitwise AND:
for(size_t i=0; i<sizeof(X)*8; i++)
if(X & (1<<i))
printf("%d", i);
If performance is important, then you'd make a look-up table with all possible results instead.
In a while loop, keep shifting right until X==1, record how many times you have to shift right and the counter will give you N.
int var = X;
int count = 0;
while (var != 1){
var >>= 1;
count++;
}
printf("N is %d", count);
Try this (flsl from here which is available from string.h on macOS) :
int flsl(long mask)
{
int bit;
if (mask == 0) return (0);
for (bit = 1; mask != 1; bit++)
mask = (unsigned long)mask >> 1;
return (bit);
}
unsigned char binlog(long mask) { return mask ? flsl(mask) - 1 : 0; }
int x = 1 << 20;
printf("%d\n", binlog(x)); ===> 20
Related
I am reviewing for an exam and have a practice problem that I'm stuck on.
I need to write the function find_sequence(unsigned int num, unsigned int patter) {}.
I have tried comparing num & (pattern << i) == (pattern << i) and other things like that but it keeps saying there is a pattern when there isn't. I see why it is doing that but I can not fix it.
The num I'm using is unsigned int a = 82937 and I'm searching for pattern unsigned int b = 0x05.
Pattern: 00000000000000000000000000000101
Original bitmap: 00000000000000010100001111111001
The code so far:
int find_sequence(unsigned int num, unsigned int pattern)
{
for (int i=0; i<32; i++)
{
if ((num & (pattern << i)) == (pattern << i))
{
return i;
}
}
return -9999;
}
int
main()
{
unsigned int a = 82937;
unsigned int b = 0x05;
printf("Pattern: ");
printBits(b);
printf("\n");
printf("Original bitmap: ");
printBits(a);
printf("\n");
int test = find_sequence(a, b);
printf("%d\n", test);
return 0;
}
Here is what I have so far. This keeps returning 3, and I see why but I do not know how to avoid it.
for (int i=0; i<32; i++)
{
if ((num & (pattern << i)) == (pattern << i))
is bad:
- it works only when pattern consists of 1 entirely
- you generate at the end of the loop pattern << 31 which is 0 when pattern is even. Condition will hold every time then.
Knowing the length of the pattern would simplify the loop above; just go until 32 - size. When not given by the API, the length can be calculated either by a clz() function or manually by looping over the bits.
Now, you can generate the mask as mask = (1u << length) - 1u (note: you have to handle the length == 32 case in a special way) and write
for (int i=0; i < (32 - length); i++)
{
if ((num & (mask << i)) == (pattern << i))
or
for (int i=0; i < (32 - length); i++)
{
if (((num >> i) & mask) == pattern)
((num & (pattern << i)) == (pattern << i)) won't give you the desire results.
Let's say you pattern is 0b101 and the value is 0b1111, then
0101 pattern
1111 value
& ----
0101 pattern
Even though the value has not the pattern 0b101, the check would return true.
You've got to create a mask where all bits of the pattern (until the most
significant bit) are 1 and the rest are 0. So for the pattern 0b101 the mask
must be b111.
So first you need to calculate the position of the most significant bit of the pattern, then create
the mask and then you can apply (bitwise AND) the mask to the value. If the
result is the same as the pattern, then you've found your pattern:
int find_sequence(unsigned int num, unsigned int pattern)
{
unsigned int copy = pattern;
// checking edge cases
if(num == 0 && pattern == 0)
return 0;
if(num == 0)
return -1;
// calculating msb of pattern
int msb = -1;
while(copy)
{
msb++;
copy >>= 1;
}
printf("msb of pattern at pos: %d\n", msb);
// creating mask
unsigned int mask = (1U << msb + 1) - 1;
int pos = 0;
while(num)
{
if((num & mask) == pattern)
return pos;
num >>= 1;
pos++;
}
return -1;
}
Using this function I get the value 14, where your 0b101 pattern is found in
a.
In this case you could make a bitmask that 0's out all the spaces you aren't looking for so in this case
Pattern: 00000000000000000000000000000101
Bitmask: 00000000000000000000000000000111
So in the case of the number you are looking at
Original: 00000000000000010100001111111001
If you and that with this bitmask you end of with
Number after &: 00000000000000000000000000000001
And compare the new number with your pattern to see if equal.
Then >> the original number
Original: 00000000000000010100001111111001
Right shifted: 00000000000000001010000111111100
And repeat the & and compare to check the next 3 numbers in the sequence.
I'm wondering if someone know effective approach to calculate bits in specified position along array?
Assuming that OP wants to count active bits
size_t countbits(uint8_t *array, int pos, size_t size)
{
uint8_t mask = 1 << pos;
uint32_t result = 0;
while(size--)
{
result += *array++ & mask;
}
return result >> pos;
}
You can just loop the array values and test for the bits with a bitwise and operator, like so:
int arr[] = {1,2,3,4,5};
// 1 - 001
// 2 - 010
// 3 - 011
// 4 - 100
// 5 - 101
int i, bitcount = 0;
for (i = 0; i < 5; ++i){
if (arr[i] & (1 << 2)){ //testing and counting the 3rd bit
bitcount++;
}
}
printf("%d", bitcount); //2
Note that i opted for 1 << 2 which tests for the 3rd bit from the right or the third least significant bit just to be easier to show. Now bitCount would now hold 2 which are the number of 3rd bits set to 1.
Take a look at the result in Ideone
In your case you would need to check for the 5th bit which can be represented as:
1 << 4
0x10000
16
And the 8th bit:
1 << 7
0x10000000
256
So adjusting this to your bits would give you:
int i, bitcount8 = 0, bitcount5 = 0;
for (i = 0; i < your_array_size_here; ++i){
if (arr[i] & 0x10000000){
bitcount8++;
}
if (arr[i] & 0x10000){
bitcount5++;
}
}
If you need to count many of them, then this solution isn't great and you'd be better off creating an array of bit counts, and calculating them with another for loop:
int i, j, bitcounts[8] = {0};
for (i = 0; i < your_array_size_here; ++i){
for (j = 0; j < 8; ++j){
//j will be catching each bit with the increasing shift lefts
if (arr[i] & (1 << j)){
bitcounts[j]++;
}
}
}
And in this case you would access the bit counts by their index:
printf("%d", bitcounts[2]); //2
Check this solution in Ideone as well
Let the bit position difference (e.g. 7 - 4 in this case) be diff.
If 2diff > n, then code can add both bits at the same time.
void count(const uint8_t *Array, size_t n, int *bit7sum, int *bit4sum) {
unsigned sum = 0;
unsigned mask = 0x90;
while (n > 0) {
n--;
sum += Array[n] & mask;
}
*bit7sum = sum >> 7;
*bit4sum = (sum >> 4) & 0x07;
}
If the processor has a fast multiply and n is still not too large, like n < pow(2,14) in this case. (Or n < pow(2,8) in the general case)
void count2(const uint8_t *Array, size_t n, int *bit7sum, int *bit4sum) {
// assume 32 bit or wider unsigned
unsigned sum = 0;
unsigned mask1 = 0x90;
unsigned m = 1 + (1u << 11); // to move bit 7 to the bit 18 place
unsigned mask2 = (1u << 18) | (1u << 4);
while (n > 0) {
n--;
sum += ((Array[n] & mask1)*m) & mask2;
}
*bit7sum = sum >> 18;
*bit4sum = ((1u << 18) - 1) & sum) >> 4);
}
Algorithm: code is using a mask, multiply, mask to separate the 2 bits. The lower bit remains in it low position while the upper bit is shifted to the upper bits. Then a parallel add occurs.
The loop avoids any branching aside from the loop itself. This can make for fast code. YMMV.
With even larger n, break it down into multiple calls to count2()
I want to XOR two numbers as follows:
11001110 and 110
However, I need to align the bit patterns as such:
11001110
11000000
Any ideas how to do this? I imagine some bitwise operation might be needed, although how would I know how many bits to shift by?
Here's one attempt, assuming I got the requirements right:
int topbit(unsigned int x)
{
for (int i = CHAR_BIT * sizeof x - 1; i >= 0; --i)
{
if (x & (1u << i))
return i;
}
return -1;
}
unsigned int alignedxor(unsigned int a, unsigned int b)
{
const int topa = topbit(a);
const int topb = topbit(b);
if (topa < 0)
return b;
if (topb < 0)
return a;
if (topa > topb)
return a ^ (b << (topa - topb));
return (a << (topb - topa)) ^ b;
}
int main(void) {
printf("%x\n", alignedxor(0xce, 6));
printf("%x\n", alignedxor(6, 0xce));
return 0;
}
This prints e, twice, which seems correct but that's all the testing I did.
And yes, you can get the index of the topmost 1-bit more efficiently, but who cares? Also used my rich imagination to deal with corner cases (such as one number being 0).
To know how many bits to shift on Windows you can use this MS-specific function: _BitScanReverse or you can implement your own, something along the lines of:
int findFirstSetBit(uint32_t _n)
{
int idx = 31;
for( ; idx >= 0; --idx){
if(_n & (1 << idx) != 0){
return idx;
}
}
return -1;
}
#include <stdio.h>
int main()
{
int num, i = 0,pos;
printf(" Enter num \n");
scanf("%d",&num);
for( i = 0; i < 31; i++ )
{
pos = 1 << i;
if ( num & pos )
printf("1");
else
printf("0");
}
printf("\n");
return 0;
}
/*
O/P
Enter Num
12
0011000000000000
*/
But i want to print the o/p as 0000000000001100
So, What are the changes i have to made to get the desired o/p
You're printing the least significant bit first. Change your for loop to count down:
for (int i = 31; i >= 0; i--)
EDIT:
Seem that I'm the one who overlooked desired output. So the solutions provided by others will work for the OP.
I'm surprised people overlooked the fact that endianness usually applies to byte level instead of bit, which make the plain index-based loop fail to provide required output.
for a decimal to big-endian byte, you need :
while (num)
{
big <<= 8;
big |= num & 0xFF;
num >>= 8;
}
so in order to output little-endian integer into big-endian binaries, you need :
// 'num' was 4-byte (int) data in little-endian format
while (num)
{
// select required byte block
unsigned char curByte = num & 0xFF;
// prints the byte binaries
for(int iBit=7; iBit>=0; --iBit)
{
unsigned char theBit = curByte >> iBit;
if (theBit & 0x1)
putchar('1');
else
putchar('0');
}
// shifts to next byte block
num >>= 8;
}
Change your for loop to be more like:
#define BIT(x) (1U << (x))
for (i = 31; i >= 0; --i)
{
if (x & BIT(i)) {
putchar('1');
}
else {
putchar('0');
}
}
I want to extract bits of a decimal number.
For example, 7 is binary 0111, and I want to get 0 1 1 1 all bits stored in bool. How can I do so?
OK, a loop is not a good option, can I do something else for this?
If you want the k-th bit of n, then do
(n & ( 1 << k )) >> k
Here we create a mask, apply the mask to n, and then right shift the masked value to get just the bit we want. We could write it out more fully as:
int mask = 1 << k;
int masked_n = n & mask;
int thebit = masked_n >> k;
You can read more about bit-masking here.
Here is a program:
#include <stdio.h>
#include <stdlib.h>
int *get_bits(int n, int bitswanted){
int *bits = malloc(sizeof(int) * bitswanted);
int k;
for(k=0; k<bitswanted; k++){
int mask = 1 << k;
int masked_n = n & mask;
int thebit = masked_n >> k;
bits[k] = thebit;
}
return bits;
}
int main(){
int n=7;
int bitswanted = 5;
int *bits = get_bits(n, bitswanted);
printf("%d = ", n);
int i;
for(i=bitswanted-1; i>=0;i--){
printf("%d ", bits[i]);
}
printf("\n");
}
As requested, I decided to extend my comment on forefinger's answer to a full-fledged answer. Although his answer is correct, it is needlessly complex. Furthermore all current answers use signed ints to represent the values. This is dangerous, as right-shifting of negative values is implementation-defined (i.e. not portable) and left-shifting can lead to undefined behavior (see this question).
By right-shifting the desired bit into the least significant bit position, masking can be done with 1. No need to compute a new mask value for each bit.
(n >> k) & 1
As a complete program, computing (and subsequently printing) an array of single bit values:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv)
{
unsigned
input = 0b0111u,
n_bits = 4u,
*bits = (unsigned*)malloc(sizeof(unsigned) * n_bits),
bit = 0;
for(bit = 0; bit < n_bits; ++bit)
bits[bit] = (input >> bit) & 1;
for(bit = n_bits; bit--;)
printf("%u", bits[bit]);
printf("\n");
free(bits);
}
Assuming that you want to calculate all bits as in this case, and not a specific one, the loop can be further changed to
for(bit = 0; bit < n_bits; ++bit, input >>= 1)
bits[bit] = input & 1;
This modifies input in place and thereby allows the use of a constant width, single-bit shift, which may be more efficient on some architectures.
Here's one way to do it—there are many others:
bool b[4];
int v = 7; // number to dissect
for (int j = 0; j < 4; ++j)
b [j] = 0 != (v & (1 << j));
It is hard to understand why use of a loop is not desired, but it is easy enough to unroll the loop:
bool b[4];
int v = 7; // number to dissect
b [0] = 0 != (v & (1 << 0));
b [1] = 0 != (v & (1 << 1));
b [2] = 0 != (v & (1 << 2));
b [3] = 0 != (v & (1 << 3));
Or evaluating constant expressions in the last four statements:
b [0] = 0 != (v & 1);
b [1] = 0 != (v & 2);
b [2] = 0 != (v & 4);
b [3] = 0 != (v & 8);
Here's a very simple way to do it;
int main()
{
int s=7,l=1;
vector <bool> v;
v.clear();
while (l <= 4)
{
v.push_back(s%2);
s /= 2;
l++;
}
for (l=(v.size()-1); l >= 0; l--)
{
cout<<v[l]<<" ";
}
return 0;
}
Using std::bitset
int value = 123;
std::bitset<sizeof(int)> bits(value);
std::cout <<bits.to_string();
#prateek thank you for your help. I rewrote the function with comments for use in a program. Increase 8 for more bits (up to 32 for an integer).
std::vector <bool> bits_from_int (int integer) // discern which bits of PLC codes are true
{
std::vector <bool> bool_bits;
// continously divide the integer by 2, if there is no remainder, the bit is 1, else it's 0
for (int i = 0; i < 8; i++)
{
bool_bits.push_back (integer%2); // remainder of dividing by 2
integer /= 2; // integer equals itself divided by 2
}
return bool_bits;
}
#include <stdio.h>
int main(void)
{
int number = 7; /* signed */
int vbool[8 * sizeof(int)];
int i;
for (i = 0; i < 8 * sizeof(int); i++)
{
vbool[i] = number<<i < 0;
printf("%d", vbool[i]);
}
return 0;
}
If you don't want any loops, you'll have to write it out:
#include <stdio.h>
#include <stdbool.h>
int main(void)
{
int num = 7;
#if 0
bool arr[4] = { (num&1) ?true: false, (num&2) ?true: false, (num&4) ?true: false, (num&8) ?true: false };
#else
#define BTB(v,i) ((v) & (1u << (i))) ? true : false
bool arr[4] = { BTB(num,0), BTB(num,1), BTB(num,2), BTB(num,3)};
#undef BTB
#endif
printf("%d %d %d %d\n", arr[3], arr[2], arr[1], arr[0]);
return 0;
}
As demonstrated here, this also works in an initializer.