Comment comptez-vous le nombre de bits défini dans un nombre à virgule flottante?

Comment comptez-vous le nombre de bits définis dans un nombre à virgule flottante à l’aide de fonctions C?

#include  /* for printf() */ #include  /* 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; } 

Si vous souhaitez travailler sur la représentation au niveau du bit d’un nombre à virgule flottante, procédez comme suit:

 float f; /* whatever your float is */ int i = *(int *)&f; 

Cela prend l’adresse de f avec l’adresse de l’opérateur, & . Cette adresse est du type float * , un pointeur sur un float. Ensuite, il le réclame avec (int *) , qui dit “prétend que ce pointeur ne pointe plus vers un float , mais qu’il pointe maintenant vers un int “. Notez que cela ne change pas la valeur en f . Ensuite, le dernier * (ou le premier, puisque nous lisons de droite à gauche) déréférence ce pointeur, qui est un pointeur sur un int , et renvoie donc un int , autrement dit l’entier ayant la même représentation binary que le flottant.

Pour faire le contraire (convertir et retourner en un float f ), faire le contraire:

 f = *(float *)&i; 

Sauf erreur de ma part, cette opération n’est pas définie par la norme C, mais fonctionnera probablement avec la plupart des ordinateurs et des compilateurs. Il n’est pas défini car je pense que la représentation réelle des nombres en virgule flottante dépend de la mise en oeuvre et peut être laissée à la CPU ou au compilateur. Par conséquent, la valeur de i est presque impossible à prédire après cette opération (il en va de même pour la valeur de f dans l’opération inverse). Il est célèbre dans la fonction de racine carrée inverse de John Carmack dans le même but néfaste.

Quoi qu’il en soit, si vous faites cela dans du code réel, vous devriez probablement vous arrêter et réfléchir à ce que vous essayez de faire et pourquoi vous utilisez des float pour le faire. Cependant, si vous le faites par curiosité ou si vous y avez pensé et que vous êtes certain de votre conception et de vos méthodes, foncez.

Je suis porté à croire que vous savez déjà comment compter le nombre de bits définis dans un entier normal, car c’est une tâche beaucoup plus facile. Si vous ne le savez pas, votre compilateur (ou le langage C, je ne sais même pas) peut avoir une fonction permettant de compter les bits, ou vous pouvez utiliser quelque chose du merveilleux site Web Bit-Twiddling Hacks , qui contient des moyens de faire des choses comme ceci avec les opérations au niveau des bits (ce qui devrait être assez rapide).

Une fonction intéressante pour compter les bits définis dans un entier mentionné par la première réponse:

 int NumberOfSetBits(int i) { i = i - ((i >> 1) & 0x55555555); i = (i & 0x33333333) + ((i >> 2) & 0x33333333); return ((i + (i >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; } 

Pour l’utiliser sur votre float, vous feriez quelque chose comme ceci:

 //... float f; //... int numBitsOfF = NumberOfSetBits(*(int*) &f); 

Vous voulez dire les bits définis dans la représentation simple précision d’un nombre IEEE-754? Si c’est le cas, convertissez-le en int (float et int ont une largeur de 32 bits) et effectuez un nombre de bits normal: SO question # 109023 .

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