How do you count the number of bits set in a floating point number using C functions?
-
for performance measure? – Jek Oct 02 '16 at 05:30
5 Answers
#include <stdio.h> /* for printf() */
#include <limits.h> /* for CHAR_BIT */
int main(void) {
/* union method */
{
/* a union can only be initialized for the first option in the union */
union { float f; char cs[sizeof(float)]; } const focs = { 1.0 };
int j,k;
int count = 0;
for (j = 0; j < sizeof(float); j++)
{
char const byte = focs.cs[j];
for (k = 0; k < CHAR_BIT; k++)
{
if ((1 << k) & byte)
{
count++;
}
}
}
printf("count(%2.1f) = %d\n", focs.f, count);
}
/* cast method */
{
float const f = 2.5;
int j,k;
int count = 0;
for (j = 0; j < sizeof(float); j++)
{
char const byte = ((char *)&f)[j];
for (k = 0; k < CHAR_BIT; k++)
{
if ((1 << k) & byte)
{
count++;
}
}
}
printf("count(%2.1f) = %d\n", f, count);
}
return 0;
}

- 87,131
- 49
- 199
- 315
-
I forgot about the union hack! But you should use sizeof(float) instead of sizeof(int). Also, int and float are the same size on most systems, but I can't find any standards saying anything about their relative sizes (or anything about float sizes), so I can't be sure - but wouldn't it be nicer to only have 1 for() loop and use a union of float and int instead? – Chris Lutz Jul 13 '09 at 18:41
-
That's the thing - I think implementation-wise, they're almost always the same, but I don't know of any standard that dictates so, which is why I did it this way. I could still compress the two loops by doing `int i; int count=0; for (i = 0; i < 8*sizeof(float); i++) { if ((1 << (i%8)) & focs.cs[i/8]) { count++; } }` – rampion Jul 13 '09 at 19:17
-
Allthough by this(http://stackoverflow.com/questions/881894/is-char-guaranteed-to-be-exactly-8-bit-long-in-c) I should be using `CHAR_BIT` instead of 8 (though I safe with assuming `sizeof(char) == 1`, since that's by definition). – rampion Jul 13 '09 at 19:23
-
1sizeof(char) will always be 1, but your code could (theoretically) be running on a PDP-7, where CHAR_BIT would be 18 (!). – Chris Lutz Jul 13 '09 at 22:16
If you want to work on the actual bitwise representation of a floating point number, you should do something like this:
float f; /* whatever your float is */
int i = *(int *)&f;
What this does is take the address of f
with the address-of operator, &
. This address is of type float *
, a pointer to a float. Then it recasts it with (int *)
, which says "pretend this pointer doesn't point to a float
anymore, but now it points to an int
". Note that it doesn't change the value at f
at all. Then the last *
(or first, since we read right-to-left) dereferences this pointer, which is a pointer to an int
, and therefore returns an int
, a.k.a. the integer with the same bitwise representation as the float.
To do the opposite (convert and int i
back to a float f
), do the opposite:
f = *(float *)&i;
Unless I am mistaken, this operation is undefined by the C standard, but will probably work on most computers and compilers. It is undefined because I believe the actual floating-point representation of numbers is implementation-dependent, and can be left to the CPU or the compiler, and therefore the value of i
is almost impossible to predict after this operation (same goes for the value of f
in the reverse operation). It is famously used in John Carmack's inverse square root function for the same nefarious purpose.
Anyway, if you're doing this in real code, you should probably stop and think twice about what you're trying to do and why you're using float
s to do it. However, if you're just doing this out of curiosity, or you have thought about these and are sure of your design and methods, go for it.
I'm led to believe that you already know how to count the number of bits set in a regular integer, as this is a much easier task. If you don't know, your compiler (or the C language, I don't even know) may have a function to count bits, or you could use something from the wonderful Bit-Twiddling Hacks website, which has ways to do things like this with bitwise operations (which should be pretty fast).

- 73,191
- 16
- 130
- 183
-
1It's undefined not just because of that -- GCC (in certain configurations) will warn **dereferencing type-punned pointer will break strict-aliasing rules** with good reason, as this really does break the assumption (from ISO C that benefits performance) that two pointers to distinct simple types (other than `char`) never point to the same object. – ephemient Jul 13 '09 at 19:24
-
3@sigjuice: the two pointers are the float* created by doing &f, and the int* created by casting that float*. The compiler is perfectly entitled to re-order the memory access operations such that the memory location is read into i before f is initialised, which is why the behaviour is undefined. – Steve Jessop Jul 13 '09 at 21:07
-
Use `memcpy` or a `union`. Casting `*(float*)&i` violates strict aliasing. [Reliable type-punning across C and C++ standards](https://stackoverflow.com/q/58674606) – Peter Cordes Dec 05 '22 at 15:48
A nice function for counting set bits in an integer mentioned by the first answer:
int NumberOfSetBits(int i)
{
i = i - ((i >> 1) & 0x55555555);
i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
return ((i + (i >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
}
To use it on your float you would do something like this:
//...
float f;
//...
int numBitsOfF = NumberOfSetBits(*(int*) &f);

- 653
- 6
- 15
-
You need `memcpy` or `union` to safely type-pun in C. Don't cast pointers; that's strict-aliasing UB. [Reliable type-punning across C and C++ standards](https://stackoverflow.com/q/58674606) . For the actual popcount, yes, that or a builtin like GNU C `__builtin_popcount`. [Count the number of set bits in a 32-bit integer](https://stackoverflow.com/q/109023) – Peter Cordes Dec 05 '22 at 15:50
You mean the bits set in the IEEE-754 single precision representation of a number? If so, cast it to int (both float and int are 32bit wide) and do a regular bit count: SO question #109023.

- 1
- 1

- 7,249
- 5
- 33
- 54
-
2Casting to int will truncate and convert, not give you the raw representation. – bdonlan Jul 13 '09 at 18:18
-
2Good point. So a better solution would be to union it or float f; *(int*)&f – Adrian Panasiuk Jul 13 '09 at 18:19
-
1
-
1http://stackoverflow.com/questions/109023/best-algorithm-to-count-the-number-of-set-bits-in-a-32-bit-integer – Adrian Panasiuk Jul 13 '09 at 18:29
-
1I would use *(`unsigned int*)&f`. Unsigned types behave better (no sign mess). – Johannes Schaub - litb Jul 13 '09 at 19:02
-
You need `memcpy` or `union` to safely type-pun in C. Don't cast pointers; that's strict-aliasing UB. [Reliable type-punning across C and C++ standards](https://stackoverflow.com/q/58674606) – Peter Cordes Dec 05 '22 at 15:49
The following function will find the number of bits in a 32-bit number. Just type case your float with integer and call this function by a cast
float f=3.14f;
count_bits(*(int *)&f);
int count_bits(int v)
{
// count the number of bits set in v
int c; // c accumulates the total bits set in v
int b=v;
for (c = 0; v; c++)
{
v &= v - 1; // clear the least significant bit set
}
//printf("No of bits in %d is %d\n",b,c);
return c;
}

- 477
- 6
- 13