您如何计算浮点数中设置的位数?

时间:2009-07-13 18:14:19

标签: c floating-point

如何使用C函数计算浮点数中设置的位数?

5 个答案:

答案 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;
}