=============================运行结果
4296000 -> 10000011000110101000000
a1_bitcount: num of 1=7, time=782 ms
a2_bitcount: num of 1=7, time=265 ms
a3_bitcount: num of 1=7, time=938 ms
a4a_bitcount: num of 1=7, time=78 ms
a4b_bitcount: num of 1=7, time=62 ms
=============================运行结果end
Playing
=============================文件列表
src/main.c
src/lib/bitCount.c
src/lib/showBinary.c
src/lib/ut.h
src/lib/pre16.h
src/lib/pre8.h
=============================代码
src/main.c
#include <stdio.h> #include <stdlib.h> #include <time.h> #include "lib/ut.h" typedef int (*FunctionCallback)(unsigned int); FunctionCallback functions[] = { &a1_bitcount, &a2_bitcount, &a3_bitcount , &a4a_bitcount, &a4b_bitcount}; char * names[]={"a1_bitcount", "a2_bitcount", "a3_bitcount" , "a4a_bitcount", "a4b_bitcount"}; void testFun(int fIdx, unsigned int num) { int rlt; long i; clock_t start = clock(); //注意,这里多运行n次,只是为了测试时间方便。 for (i = 0; i < 10000000; i++) { rlt = functions[fIdx](num); } double time = ((double) clock() - start); // / CLOCKS_PER_SEC printf(" %s: num of 1=%d, time=%.0f ms\n", names[fIdx], rlt, time); } int main(void) { //unsigned int num = 4294967295; unsigned int num = 4296000; //unsigned int num = -1; int funSize = sizeof(functions) / sizeof(FunctionCallback); showBinary(num); int i; for(i=0;i<funSize;i++){ testFun(i, num); } return EXIT_SUCCESS; }
src/lib/bitCount.c
/* * bitCount.c * http://gurmeet.net/puzzles/fast-bit-counting-routines/ */ #include "ut.h" #include "pre8.h" #include "pre16.h" //1. Iterated Count int a1_bitcount(unsigned int n) { int count = 0; while (n) { count += n & 0x1u; n >>= 1; } return count; } //2. Sparse Ones int a2_bitcount(unsigned int n) { int count = 0; while (n) { count++; n &= (n - 1); } return count; } //3. Dense Ones int a3_bitcount(unsigned int n) { int count = 8 * sizeof(int); n ^= (unsigned int) -1; while (n) { count--; n &= (n - 1); } return count; } //4a. Precompute-8bit int a4a_bitcount(unsigned int n) { // works only for 32-bit ints return bits_in_char[n & 0xffu] + bits_in_char[(n >> 8) & 0xffu] + bits_in_char[(n >> 16) & 0xffu] + bits_in_char[(n >> 24) & 0xffu]; } //4b. Precompute-16bit int a4b_bitcount (unsigned int n) { // works only for 32-bit ints return bits_in_16bits [n & 0xffffu] + bits_in_16bits [(n >> 16) & 0xffffu] ; }
src/lib/showBinary.c
/* * http://stackoverflow.com/questions/699968/display-the-binary-representation-of-a-number-in-c */ #include <stdlib.h> #include <stdio.h> #include <string.h> #include "ut.h" #define SZ 32 /* Create a string of binary digits based on the input value. Input: val: value to convert. buff: buffer to write to must be >= sz+1 chars. sz: size of buffer. Returns address of string or NULL if not enough space provided. */ static char *binrep(unsigned int val, char *buff, int sz) { char *pbuff = buff; /* Must be able to store one character at least. */ if (sz < 1) return NULL; /* Special case for zero to ensure some output. */ if (val == 0) { *pbuff++ = '0'; *pbuff = '\0'; return buff; } /* Work from the end of the buffer back. */ pbuff += sz; *pbuff-- = '\0'; /* For each bit (going backwards) store character. */ while (val != 0) { if (sz-- == 0) return NULL; *pbuff-- = ((val & 1) == 1) ? '1' : '0'; /* Get next bit. */ val >>= 1; } return pbuff + 1; } void showBinary(unsigned int num) { char buff[SZ + 1]; printf("%d -> %s\n", num, binrep(num, buff, SZ)); } int main_showBinary(void) { char *argv[] = { "", "4" }; int argc = sizeof(argv) / sizeof(char *); int i; int n; for (i = 1; i < argc; i++) { n = atoi(argv[i]); showBinary(n); } return 0; }
src/lib/ut.h
#ifndef H1_H_ #define H1_H_ // here goes all the code void showBinary(unsigned int num); int a1_bitcount(unsigned int n); int a2_bitcount(unsigned int n); int a3_bitcount(unsigned int n); int a4a_bitcount(unsigned int n); int a4b_bitcount(unsigned int n); #endif /* H1_H_ */
src/lib/pre8.h
#ifndef PRE8_H_ #define PRE8_H_ static int bits_in_char [256]={ 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5 , 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6 , 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6 , 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7 , 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6 , 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7 , 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7 , 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 }; #endif /* PRE8_H_ */
src/lib/pre8.h
src/lib/pre16.h
生成上述二文件的代码在bit count in c (2) -- precompute