如何使用C函数计算浮点数中设置的位数?
答案 0 :(得分:6)
#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;
}
答案 1 :(得分:4)
如果你想处理浮点数的实际按位表示,你应该这样做:
float f; /* whatever your float is */
int i = *(int *)&f;
这样做的地方是f
地址与运营商地址&
。此地址的类型为float *
,指向float的指针。然后用(int *)
重新创建它,它说“假装这个指针不再指向float
,但现在它指向int
”。请注意,它根本不会更改f
处的值。然后最后的*
(或者,首先,因为我们从右向左阅读)取消引用这个指针,这是一个指向int
的指针,因此返回一个int
,也就是整数使用与float相同的按位表示。
要做相反的事情(将int i
转换回float f
),请执行相反的操作:
f = *(float *)&i;
除非我弄错了,否则C标准不会定义此操作,但可能适用于大多数计算机和编译器。它是未定义的,因为我认为数字的实际浮点表示是依赖于实现的,并且可以留给CPU或编译器,因此在此操作之后几乎不可能预测i
的值(相同)在反向操作中寻找f
的值。它在约翰卡马克的逆平方根函数中被用于同样的邪恶目的。
无论如何,如果你在实际代码中这样做,你应该停下来思考你正在尝试做什么以及为什么要使用float
来做这件事。但是,如果您只是出于好奇,或者您已经考虑过这些并确定您的设计和方法,那就去吧。
我认为你已经知道如何计算常规整数中设置的位数,因为这是一个更容易的任务。如果您不知道,您的编译器(或C语言,我甚至不知道)可能具有计算位数的功能,或者您可以使用来自精彩Bit-Twiddling Hacks网站的内容,其中有一些方法可以做像按位操作这样的事情(应该非常快)。
答案 2 :(得分:3)
一个很好的函数,用于计算第一个答案提到的整数中的设置位:
int NumberOfSetBits(int i)
{
i = i - ((i >> 1) & 0x55555555);
i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
return ((i + (i >> 4) & 0xF0F0F0F) * 0x1010101) >> 24;
}
要在你的花车上使用它,你会做这样的事情:
//...
float f;
//...
int numBitsOfF = NumberOfSetBits(*(int*) &f);
答案 3 :(得分:2)
你的意思是在一个数字的IEEE-754单精度表示中设置的位?如果是这样,将它转换为int(float和int都是32位宽)并执行常规位计数:SO question #109023。
答案 4 :(得分:-1)
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;
}