You are given a getTemps() function returns an integer composed of: the daily high temperature
in bits 20-29, the daily low temperature in bits 10-19, and the current temperature in bits 0-9, all
as 2's complement 10-bit integers.
Write a C program which extracts the high, low, and current temperature and prints the values.
I am given this situation. So my question is how do I get the specific segments of an integer.
So far I have:
#include <stdio.h>
unsigned createMask(unsigned a, unsigned b){
unsigned r = 0;
unsigned i;
for (i=a; i<=b; i++){
r |= 1 << i;
}
return r;
}
int main(int argc, char *argv[])
{
unsigned r = createMask(29,31);
int i = 23415;
unsigned result = r & i;
printf("%d\n", i);
printf("%u\n", result);
}
The integer 23415 for example would have the binary 00000000 00000000 01011011 01110111
Then bits 29 through 31 for example should be 111 or integer -1 since its 2's complement.
There are three basic approaches for extracting encoded information from a bitfield. The first two are related and differ only in the manner the bitfield struct is initialized. The first and shortest is to simply create a bitfield struct defining the bits associated with each member of the struct. The sum of the bits cannot exceed sizeof type * CHAR_BIT bits for the type used to create the bitfield. A simple example is:
#include <stdio.h>
typedef struct {
unsigned cur : 10,
low : 10,
high : 10;
} temps;
int main (void) {
unsigned n = 0; /* encoded number of temps */
n = 58; /* fill number (58, 46, 73) */
n |= (46 << 10);
n |= (73 << 20);
temps t = *(temps *)&n; /* initialize struct t */
/* output value and temps */
printf ("\n number entered : %u\n\n", n);
printf (" %2hhu - %2hhu value : %u (deg. F)\n", 0, 9, t.cur);
printf (" %2hhu - %2hhu value : %u (deg. F)\n", 10, 19, t.low);
printf (" %2hhu - %2hhu value : %u (deg. F)\n\n", 20, 29, t.high);
return 0;
}
Note: memcpy can also be used to initialize the value for the structure to avoid casting the address of n. (that was done intentionally here to avoid inclusion of string.h).
The next method involves creation of a union between the data type represented and the exact same struct discussed above. The benefit of using the union is that you avoid having to typecast, or memcpy a value to initialize the struct. You simply assign the encoded value to the numeric type within the union. The same example using this method is:
#include <stdio.h>
typedef struct {
unsigned cur : 10,
low : 10,
high : 10;
} temps;
typedef union {
temps t;
unsigned n;
} utemps;
int main (void) {
unsigned n = 0; /* encoded number of temps */
n = 58; /* fill number (58, 46, 73) */
n |= (46 << 10);
n |= (73 << 20);
utemps u; /* declare/initialize union */
u.n = n;
/* output value and temps */
printf ("\n number entered : %u\n\n", n);
printf (" %2hhu - %2hhu value : %u (deg. F)\n", 0, 9, u.t.cur);
printf (" %2hhu - %2hhu value : %u (deg. F)\n", 10, 19, u.t.low);
printf (" %2hhu - %2hhu value : %u (deg. F)\n\n", 20, 29, u.t.high);
return 0;
}
Finally, the third method uses neither a struct or union and simply relies on bit shift operations to accomplish the same purpose. A quick example is:
#include <stdio.h>
#include <limits.h> /* for CHAR_BIT */
int main (void) {
unsigned n = 0; /* encoded number of temps */
unsigned char i = 0; /* loop counter */
unsigned char r = 10; /* number of bits in temps */
unsigned char s = 0; /* shift accumulator */
unsigned v = 0; /* extracted value */
n = 58; /* fill number (58, 46, 73) */
n |= (46 << 10);
n |= (73 << 20);
printf ("\n number entered : %u\n\n", n);
/* extract and output temps from n */
for (i = 0; i < (sizeof n * CHAR_BIT)/r; i++)
{
v = (n >> i * r) & 0x3ff;
printf (" %2hhu - %2hhu value : %u (deg. F)\n", s, s + r - 1, v);
s += r;
}
printf ("\n");
return 0;
}
Note: you can automate the creation of the mask with the createMask function. While longer, the shift method is not computationally intensive as shift operations take little to accomplish. While negligible, the multiplication could also be replaced with a shift and addition to further tweak performance. The only costly instruction is the division to set the loop test clause, but again it is negligible and all of these cases are likely to be optimized by the compiler.
All of the examples above produce exactly the same output:
$ ./bin/bit_extract_shift
number entered : 76593210
0 - 9 value : 58 (deg. F)
10 - 19 value : 46 (deg. F)
20 - 29 value : 73 (deg. F)
You can use union and bit field to do it. Try something like this:
struct TEM_BITS {
unsigned int tem_high :10;
unsigned int tem_low :10;
unsigned int tem_cur :10;
};
union TEM_U {
int tem_values;
struct TEM_BITS bits;
}
TEM_U t;
t.tem_values = 12345;
printf("tem_high : 0x%X\n", t.bits.tem_high);
printf("tem_low : 0x%X\n", t.bits.tem_low);
printf("tem_cur : 0x%X\n", t.bits.tem_cur);
I might have my bits backwards, but the following should be close.
int current=x&0x3ff;
int low = (x>>10)&0x3ff;
int high = (x>>20)&0x3ff;
Related
A bit new to C programming but I've made a binary mask in my program and there are following 0 on the wrong side.
Hex: 0x61
Binary Result: 0110000100000000
Binary Want: 0000000001100001
Is there a way I could shift them down to start from LSB instead?
Back of my mind is maybe, inverse the masking? Just a hunch.
Here's my function:
void printBin(char Key)
{
int count;
int bits = 16;
unsigned int mask = 1 << --bits;
for(count = 0; count <= bits; count++)
{
if( Key & mask)
{
printw("1");
}
else
{
printw("0");
}
Key <<= 1;
}
}
When you are trying to print a binary string, when you loop over your number shifting the bits as you are, you end up with the bits in reverse order. While you can simply print the binary representation, it is far easier to save binary representation to a character string (so you can save it in the correct order) and return a pointer to a statically declared string.
The 3 functions below (1) binstr returns a simple binary string containing only the number of bits that make up the representation; (2) binpad returns a binary string padded to sz bits (so you can print all 64-bits of a 64-bit number, including the leading zeros) and (3) binfmt that returns a string padded to sz bits in szs bit groups separated by sep character.
To use the functions, simply declare the constants that tell whether your computer is 32/64 bit, that will set the number of BITS_PER_LONG along with CHAR_BIT (generally 8). Their use is shown below in the example:
#include <stdio.h>
#include <stdlib.h>
/* CHAR_BIT */
#ifndef CHAR_BIT
# define CHAR_BIT 8
#endif
/* BUILD_64 */
#if defined(__LP64__) || defined(_LP64)
# define BUILD_64 1
#endif
/* BITS_PER_LONG */
#ifdef BUILD_64
# define BITS_PER_LONG 64
#else
# define BITS_PER_LONG 32
#endif
/* (note: adjust as required if not using x86/x86_64) */
char *binstr (unsigned long n);
char *binpad (unsigned long n, size_t sz);
char *binfmt (unsigned long n, unsigned char sz, unsigned char szs, char sep);
int main (int argc, char **argv) {
unsigned long v = argc > 1 ? strtoul (argv[1], NULL, 10) : 237;
unsigned long sz = argc > 2 ? strtoul (argv[2], NULL, 10) : sizeof v * CHAR_BIT;
unsigned long szs = argc > 3 ? strtoul (argv[3], NULL, 10) : CHAR_BIT;
/* print 16-bit binary representation */
printf ("\n binstr (%lu)\n %s\n", v, binstr (v));
printf ("\n binpad (%lu, %lu)\n %s\n", v, sz/4, binpad (v, sz/4));
printf ("\n binfmt (%lu, %lu, %hhu, %c)\n %s\n",
v, sz/4, (unsigned)szs/2, '-', binfmt (v, sz/4, szs/2, '-'));
/* print 32-bit binary representation */
printf ("\n binpad (%lu, %lu)\n %s\n", v, sz/2, binpad (v, sz/2));
printf ("\n binfmt (%lu, %lu, %hhu, %c)\n %s\n",
v, sz/2, (unsigned)szs, '-', binfmt (v, sz/2, szs, '-'));
/* print 64-bit binary representation */
printf ("\n binpad (%lu, %lu)\n %s\n", v, sz, binpad (v, sz));
printf ("\n binfmt (%lu, %lu, %hhu, %c)\n %s\n",
v, sz, (unsigned)szs, '-', binfmt (v, sz, szs, '-'));
return 0;
}
/** simple return of binary string */
char *binstr (unsigned long n)
{
static char s[BITS_PER_LONG + 1] = {0};
char *p = s + BITS_PER_LONG;
if (!n) {
*s = '0';
return s;
}
for (; n; n >>= 1)
*--p = (n & 1) ? '1' : '0';
return p;
}
/** returns pointer to binary representation of 'n' zero padded to 'sz'.
* returns pointer to string contianing binary representation of
* unsigned 64-bit (or less ) value zero padded to 'sz' digits.
*/
char *binpad (unsigned long n, size_t sz)
{
static char s[BITS_PER_LONG + 1] = {0};
char *p = s + BITS_PER_LONG;
register size_t i;
for (i = 0; i < sz; i++)
*--p = (n>>i & 1) ? '1' : '0';
return p;
}
/** returns pointer to formatted binary representation of 'n' zero padded to 'sz'.
* returns pointer to string contianing formatted binary representation of
* unsigned 64-bit (or less ) value zero padded to 'sz' digits with char
* 'sep' placed every 'szs' digits. (e.g. 10001010 -> 1000-1010).
*/
char *binfmt (unsigned long n, unsigned char sz, unsigned char szs, char sep) {
static char s[BITS_PER_LONG * 2 + 1] = {0};
char *p = s + BITS_PER_LONG;
unsigned char i;
for (i = 0; i < sz; i++) {
p--;
if (i > 0 && szs > 0 && i % szs == 0)
*p-- = sep;
*p = (n >> i & 1) ? '1' : '0';
}
return p;
}
Output
$ ./bin/binstrtst
binstr (237)
11101101
binpad (237, 16)
0000000011101101
binfmt (237, 16, 4, -)
0000-0000-1110-1101
binpad (237, 32)
00000000000000000000000011101101
binfmt (237, 32, 8, -)
00000000-00000000-00000000-11101101
binpad (237, 64)
0000000000000000000000000000000000000000000000000000000011101101
binfmt (237, 64, 8, -)
00000000-00000000-00000000-00000000-00000000-00000000-00000000-11101101
Let me know if you have any questions. Hope this helps. You can test with your 0x61 (decimal 97), e.g.:
$ ./bin/binstrtst 97
binstr (97)
1100001
binpad (97, 16)
0000000001100001
binfmt (97, 16, 4, -)
0000-0000-0110-0001
binpad (97, 32)
00000000000000000000000001100001
binfmt (97, 32, 8, -)
00000000-00000000-00000000-01100001
binpad (97, 64)
0000000000000000000000000000000000000000000000000000000001100001
binfmt (97, 64, 8, -)
00000000-00000000-00000000-00000000-00000000-00000000-00000000-01100001
If you are always expecting only 8-bits, you could use right shift operator, something like this:
a = a >> 8;
this will shift the bits to its right by 8 bits.
You are applying a 16bit mask on an 8bit char. If you cast it to an int before you do your bit operations it will work as you expect it to.
void printBin(char key_8) // key_8: 0x01100001
{
int key_16 = key_8; // key_16: 0x0000000001100001
int count;
int bits = 16;
unsigned int mask = 1 << --bits; // mask: 0x1000000000000000
for(count = 0; count <= bits; count++)
{
if(key_16 & mask)
{
printw("1");
}
else
{
printw("0");
}
key_16 <<= 1;
}
}
I have a 32-bit int and I want to set the first 10 bit to a specific number.
IE
The 32-bit int is:
11101010101010110101100100010010
I want the first 10 bit to be the number 123, which is
0001111011
So the result would be
00011110111010110101100100010010
Does anyone know the easiest way I would be able to do this? I know that we have to do bit-shifting but I'm not good at it so I'm not sure
Thank you!
uint32_t result = (input & 0x3fffff) | (newval << 22);
0x3fffff masks out the highest 10 bits (it has the lowest 22 bits set). You have to shift your new value for the highest 10 bits by 22 places.
Convert inputs to unsigned 32-bit integers
uint32_t num = strtoul("11101010101010110101100100010010", 0, 2);
uint32_t firstbits = 123;
Mask off the lower 32-10 bits. Create mask by shifting a unsigned long 1 22 places left making 100_0000_0000_0000_0000_0000 then decrementing to 11_1111_1111_1111_1111_1111
uint32_t mask = (1UL << (32-10)) - 1;
num &= mask;
Or in firstbits shifted left by 32-10
num |= firstbits << (32-10);
Or in 1 line:
(num & (1UL << (32-10)) - 1) | (firstbits*1UL << (32-10))
Detail about firstbits*1UL. The type of firstbits is not defined by OP and may only be a 16-bit int. To insure code can shift and form an answer that exceeds 16 bits (the minimum width of int), multiple by 1UL to insure the value is unsigned and has at least 32 bit width.
You can "erase" bits (set them to 0) by using a bit wise and ('&'); bits that are 0 in either value will be 0 in the result.
You can set bits to 1 by using a bit wise or ('|'); bits that are 1 in either value will be 1 in the result.
So: and your number with a value where the first 10 bits are 0 and the rest are 1; then 'or' it with the first 10 bits you want put in, and 0 for the other bits. If you need to calculate that value, then a left-shift would be the way to go.
You can also take a mask and replace approach where you zero the lower bits required to hold 123 and then simply | (OR) the value with 123 to gain the final result. You can accomplish the exact same thing with shifts as shown by several other answers, or you can accomplish it with masks:
#include <stdio.h>
#ifndef BITS_PER_LONG
#define BITS_PER_LONG 64
#endif
#ifndef CHAR_BIT
#define CHAR_BIT 8
#endif
char *binpad2 (unsigned long n, size_t sz);
int main (void) {
unsigned x = 0b11101010101010110101100100010010;
unsigned mask = 0xffffff00; /* mask to zero lower 8 bits */
unsigned y = 123; /* value to replace zero bits */
unsigned masked = x & mask; /* zero the lower bits */
/* show intermediate results */
printf ("\n x : %s\n", binpad2 (x, sizeof x * CHAR_BIT));
printf ("\n & mask : %s\n", binpad2 (mask, sizeof mask * CHAR_BIT));
printf ("\n masked : %s\n", binpad2 (masked, sizeof masked * CHAR_BIT));
printf ("\n | 123 : %s\n", binpad2 (y, sizeof y * CHAR_BIT));
masked |= y; /* apply the final or with 123 */
printf ("\n final : %s\n", binpad2 (masked, sizeof masked * CHAR_BIT));
return 0;
}
/** returns pointer to binary representation of 'n' zero padded to 'sz'.
* returns pointer to string contianing binary representation of
* unsigned 64-bit (or less ) value zero padded to 'sz' digits.
*/
char *binpad2 (unsigned long n, size_t sz)
{
static char s[BITS_PER_LONG + 1] = {0};
char *p = s + BITS_PER_LONG;
register size_t i;
for (i = 0; i < sz; i++)
*--p = (n>>i & 1) ? '1' : '0';
return p;
}
Output
$ ./bin/bitsset
x : 11101010101010110101100100010010
& mask : 11111111111111111111111100000000
masked : 11101010101010110101100100000000
| 123 : 00000000000000000000000001111011
final : 11101010101010110101100101111011
How about using bit fields in C combined with a union? The following structure lets you set the whole 32-bit value, the top 10 bits or the bottom 22 bits. It isn't as versatile as a generic function but you can't easily make a mistake when using it. Be aware this and most solutions may not work on all integer sizes and look out for endianness as well.
union uu {
struct {
uint32_t bottom22 : 22;
uint32_t top10 : 10;
} bits;
uint32_t value;
};
Here is an example usage:
int main(void) {
union uu myuu;
myuu.value = 999999999;
printf("value = 0x%08x\n", myuu.value);
myuu.bits.top10 = 0;
printf("value = 0x%08x\n", myuu.value);
myuu.bits.top10 = 0xfff;
printf("value = 0x%08x\n", myuu.value);
return 0;
}
The output is:
value = 0x3b9ac9ff
value = 0x001ac9ff
value = 0xffdac9ff
#include<stdio.h>
int main()
{
long int decimalNumber,remainder,quotient;
int binaryNumber[100],i=1,j;
printf("Enter any decimal number: ");
scanf("%ld",&decimalNumber);
quotient = decimalNumber;
while(quotient!=0)
{
binaryNumber[i++]= quotient % 2;
quotient = quotient / 2;
}
printf("Equivalent binary value of decimal number %d: ",decimalNumber);
for(j = i -1 ;j> 0;j--)
printf("%d",binaryNumber[j]);
return 0;
}
I want the output in 8 bit binary form, but the result as shown below, is there any operator in C which can convert 7 bit data to its equivalent 8 bit data? thank you
Sample output:
Enter any decimal number: 50
Equivalent binary value of decimal number 50: 110010
Required output is 00110010 which is 8 bit, how to append a zero in MSB position?
A very convenient way it so have a function return a binary representation in the form of a string. This allows the binary representation to be used within a normal printf format string rather than having the bits spit out at the current cursor position. To specify the exact number of digits, you must pad the binary string to the required number of places (e.g. 8, 16, 32...). The following makes use of a static variable to allow the return of the buffer, but the same can easily be implemented by allocating space for the buffer with dynamically. The preprocessor checks are not required as you can simply hardwire the length of the buffer to 64 + 1, but for the sake of completeness a check for x86/x86_64 is included and BITS_PER_LONG is set accordingly.
#include <stdio.h>
#if defined(__LP64__) || defined(_LP64)
# define BUILD_64 1
#endif
#ifdef BUILD_64
# define BITS_PER_LONG 64
#else
# define BITS_PER_LONG 32
#endif
char *binstr (unsigned long n, size_t sz);
int main (void) {
printf ("\n 50 (decimal) : %s (binary)\n\n", binstr (50, 8));
return 0;
}
/* returns pointer to binary representation of 'n' zero padded to 'sz'. */
char *binstr (unsigned long n, size_t sz)
{
static char s[BITS_PER_LONG + 1] = {0};
char *p = s + BITS_PER_LONG;
register size_t i;
if (!n) {
*s = '0';
return s;
}
for (i = 0; i < sz; i++)
*(--p) = (n>>i & 1) ? '1' : '0';
return p;
}
Output
$ ./bin/bincnv
50 (decimal) : 00110010 (binary)
Note: you cannot make repeated calls in the same printf statement due to the static buffer. If you allocate dynamically, you can call the function as many times as you like in the same printf statement.
Also, note, if you do not care about padding the binary return to any specific length and just want the binary representation to start with the most significant bit, the following simpler version can be used:
/* simple return of binary string */
char *binstr (unsigned long n)
{
static char s[BITS_PER_LONG + 1] = {0};
char *p = s + BITS_PER_LONG;
if (!n) {
*s = '0';
return s;
}
while (n) {
*(--p) = (n & 1) ? '1' : '0';
n >>= 1;
}
return p;
}
Modify your code as shown below:
quotient = quotient / 2;
}
/* ---- Add the following code ---- */
{
int group_size = 8; /* Or CHAR_BIT */
int padding = group_size - ((i-1) % group_size); /* i was inited with 1 */
if(padding != group_size) {
/* Add padding */
while(padding-- != 0) binaryNumber[i++] = 0;
}
}
/* ------- Modification ends -------- */
printf("Equivalent binary value of decimal number %d: ",decimalNumber);
This code calculates the number of padding bits required to print the number and fills the padding bits with 0.
Live demo here
If you want 7 bit answer, change group_size to 7.
Use this for printing your result:
for(j = 7; j>0; j--)
printf("%d", binaryNumber[j]);
This always prints 8 binary digits.
Edit
The int array binaryNumber must be initialized with zeros to make this work:
for(int i=0; i<8; i++) binaryNumber[i] = 0;
I have a char (input) array with size 60. I want to write a function that returns certain bits of the input array.
char input_ar[60];
char output_ar[60];
void func(int bits_starting_number, int total_number_bits){
}
int main()
{
input_ar[0]=0b11110001;
input_ar[1]=0b00110011;
func(3,11);
//want output_ar[0]=0b11000100; //least significant 6 bits of input_ar[0] and most significant bits (7.8.) of input_ar[1]
//want output_ar[1]=0b00000110; //6.5.4. bits of input_ar[1] corresponds to 3 2 1. bits of output_ar[1] (110) right-aligned other bits are 0, namely 8 7 ...4 bits is zero
}
I want to ask what's the termiology of this algorithm? How can I easily write the code? Any clues appricated.
Note: I use XC8, arrray of bits are not allowed.
This answer makes the following assumptions. Bits are numbered from 1, the first bit is the MS bit of the first byte. The extracted bit array must be left-aligned. Unused bits on the right are padded with 0.
#include <stdio.h>
#include <string.h>
#include <limits.h>
#define MAX_LEN 60
#define BMASK (1 << (CHAR_BIT-1))
unsigned char input_ar[MAX_LEN];
unsigned char output_ar[MAX_LEN];
int func(int bits_starting_number, int total_number_bits) {
// return the number of bits copied
int sors_ind, sors_bit, dest_ind = 0;
int i, imask, omask;
memset (output_ar, 0, MAX_LEN); // clear the result
if (bits_starting_number < 1 || bits_starting_number > MAX_LEN * CHAR_BIT)
return 0; // bit number is out of range
if (total_number_bits < 1)
return 0; // nothing to do
bits_starting_number--;
if (bits_starting_number + total_number_bits > MAX_LEN * CHAR_BIT)
total_number_bits = MAX_LEN * CHAR_BIT - bits_starting_number;
sors_ind = bits_starting_number / CHAR_BIT;
sors_bit = CHAR_BIT - 1 - (bits_starting_number % CHAR_BIT);
imask = 1 << sors_bit;
omask = BMASK;
for (i=0; i<total_number_bits; i++) {
if (input_ar[sors_ind] & imask)
output_ar[dest_ind] |= omask; // copy a 1 bit
if ((imask >>= 1) == 0) { // shift the input mask
imask = BMASK;
sors_ind++; // next input byte
}
if ((omask >>= 1) == 0) { // shift the output mask
omask = BMASK;
dest_ind++; // next output byte
}
}
return total_number_bits;
}
void printb (int value) {
int i;
for (i=BMASK; i; i>>=1) {
if (value & i)
printf("1");
else
printf("0");
}
printf (" ");
}
int main(void) {
int i;
input_ar[0]= 0xF1; // 0b11110001
input_ar[1]= 0x33; // 0b00110011
printf ("Input: ");
for (i=0; i<4; i++)
printb(input_ar[i]);
printf ("\n");
func(3,11);
printf ("Output: ");
for (i=0; i<4; i++)
printb(output_ar[i]);
printf ("\n");
return 0;
}
Program output
Input: 11110001 00110011 00000000 00000000
Output: 11000100 11000000 00000000 00000000
First of all, the returntype: You can return a boolean array of length total_number_bits.
Inside your function you can do a forloop, starting at bits_starting_number, iterating total_number_bits times. For each number you can divide the forloopindex by 8 (to get the right char) and than bitshift a 1 by the forloopindex modulo 8 to get the right bit. Put it on the right spot in the output array (forloopindex - bits_starting_number) and you are good to go
This would become something like:
for(i = bits_starting_number; i < bits_starting_number + total_number_bits; i++) {
boolarr[i - bits_starting_number] = charray[i/8] & (1 << (i % 8));
}
I want to write a function named bitCount() in the file: bitcount.c that returns the number of bits in the binary representation of its unsigned integer argument.
Here is what I have so far:
#include <stdio.h>
int bitCount (unsigned int n);
int main () {
printf ("# 1-bits in base 2 representation of %u = %d, should be 0\n",
0, bitCount (0));
printf ("# 1-bits in base 2 representation of %u = %d, should be 1\n",
1, bitCount (1));
printf ("# 1-bits in base 2 representation of %u = %d, should be 16\n",
2863311530u, bitCount (2863311530u));
printf ("# 1-bits in base 2 representation of %u = %d, should be 1\n",
536870912, bitCount (536870912));
printf ("# 1-bits in base 2 representation of %u = %d, should be 32\n",
4294967295u, bitCount (4294967295u));
return 0;
}
int bitCount (unsigned int n) {
/* your code here */
}
Okay, when I just run this I get:
# 1-bits in base 2 representation of 0 = 1, should be 0
# 1-bits in base 2 representation of 1 = 56, should be 1
# 1-bits in base 2 representation of 2863311530 = 57, should be 16
# 1-bits in base 2 representation of 536870912 = 67, should be 1
# 1-bits in base 2 representation of 4294967295 = 65, should be 32
RUN SUCCESSFUL (total time: 14ms)
It doesn't return the correct numbers of bits.
What's the best way to return the number of bits in the binary representation of its unsigned integer argument in C?
Here's a solution that doesn't need to iterate. It takes advantage of the fact that adding bits in binary is completely independent of the position of the bit and the sum is never more than 2 bits. 00+00=00, 00+01=01, 01+00=01, 01+01=10. The first addition adds 16 different 1-bit values simultaneously, the second adds 8 2-bit values, and each one after does half as many until there's only one value left.
int bitCount(unsigned int n)
{
n = ((0xaaaaaaaa & n) >> 1) + (0x55555555 & n);
n = ((0xcccccccc & n) >> 2) + (0x33333333 & n);
n = ((0xf0f0f0f0 & n) >> 4) + (0x0f0f0f0f & n);
n = ((0xff00ff00 & n) >> 8) + (0x00ff00ff & n);
n = ((0xffff0000 & n) >> 16) + (0x0000ffff & n);
return n;
}
This is hard-coded to 32 bit integers, if yours are a different size it will need adjusting.
int bitCount(unsigned int n) {
int counter = 0;
while(n) {
counter += n % 2;
n >>= 1;
}
return counter;
}
Turns out there are some pretty sophisticated ways to compute this as answered here.
The following impl (I learned way back) simply loops knocking off the least significant bit on each iteration.
int bitCount(unsigned int n) {
int counter = 0;
while(n) {
counter ++;
n &= (n - 1);
}
return counter;
}