How do you count the number of bits set in a floating point number using C functions?
如何使用C函数计算浮点数中设置的位数?
5 个解决方案
#1
#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;
}
#2
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.
这样做的地址是f,地址为运算符&。此地址的类型为float *,指向float的指针。然后用(int *)重新创建它,它说“假装这个指针不再指向浮点数,但现在它指向一个int”。请注意,它根本不会更改f处的值。然后最后的*(或者,首先,因为我们从右向左阅读)取消引用这个指针,这是一个指向int的指针,因此返回一个int,a.k.a。这个整数具有与float相同的按位表示。
To do the opposite (convert and int i
back to a float f
), do the opposite:
要做相反的事情(转换并将int i返回到浮点数f),请执行相反的操作:
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.
除非我弄错了,否则C标准不会定义此操作,但可能适用于大多数计算机和编译器。它是未定义的,因为我认为数字的实际浮点表示是依赖于实现的,并且可以留给CPU或编译器,因此在此操作之后几乎不可能预测i的值(值相同)反向操作中的f)。它在约翰卡马克的反平方根函数中被用于同样的邪恶目的。
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).
我已经相信你已经知道如何计算常规整数中设置的位数,因为这是一个更容易的任务。如果您不知道,您的编译器(或C语言,我甚至不知道)可能具有计数位的功能,或者您可以使用来自精彩Bit-Twiddling Hacks网站的内容,该网站有办法做事像这样的按位运算(应该非常快)。
#3
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);
#4
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.
你的意思是在一个数字的IEEE-754单精度表示中设置的位?如果是这样,将它转换为int(float和int都是32位宽)并进行常规位计数:问题#109023。
#5
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;
}
#1
#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;
}
#2
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.
这样做的地址是f,地址为运算符&。此地址的类型为float *,指向float的指针。然后用(int *)重新创建它,它说“假装这个指针不再指向浮点数,但现在它指向一个int”。请注意,它根本不会更改f处的值。然后最后的*(或者,首先,因为我们从右向左阅读)取消引用这个指针,这是一个指向int的指针,因此返回一个int,a.k.a。这个整数具有与float相同的按位表示。
To do the opposite (convert and int i
back to a float f
), do the opposite:
要做相反的事情(转换并将int i返回到浮点数f),请执行相反的操作:
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.
除非我弄错了,否则C标准不会定义此操作,但可能适用于大多数计算机和编译器。它是未定义的,因为我认为数字的实际浮点表示是依赖于实现的,并且可以留给CPU或编译器,因此在此操作之后几乎不可能预测i的值(值相同)反向操作中的f)。它在约翰卡马克的反平方根函数中被用于同样的邪恶目的。
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).
我已经相信你已经知道如何计算常规整数中设置的位数,因为这是一个更容易的任务。如果您不知道,您的编译器(或C语言,我甚至不知道)可能具有计数位的功能,或者您可以使用来自精彩Bit-Twiddling Hacks网站的内容,该网站有办法做事像这样的按位运算(应该非常快)。
#3
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);
#4
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.
你的意思是在一个数字的IEEE-754单精度表示中设置的位?如果是这样,将它转换为int(float和int都是32位宽)并进行常规位计数:问题#109023。
#5
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;
}