Intereting Posts
Программно проверить, выполняется ли процесс в фоновом режиме Почему FT_Read () терпит неудачу в дочернем процессе, но работает в родительском процессе? Почему нельзя сравнивать типы с плавающей запятой, используя функцию memcmp ()? Каков лучший способ объявить фиктивные переменные для вложенных циклов? Как сообщить компилятору развернуть этот цикл C препроцессора для возврата строки, повторяемой определенное количество раз программа, которая печатает себя, как она работает? Не получать ожидаемый результат, используя cmpxchg8b для unsigned long Поплавок, установленный в 0.1, сравнивает значение false с 0,1 почему 1,2 * 30 = 35? NtDeviceIoControlFile – Получение размера буфера Почему временная сложность O (n ^ 2) в этом коде? Память косвенной адресации movl – assembly Периодически вызывается spi_write в драйвере Linux Как фильтровать и перехватывать пакеты Linux с помощью API net_dev_add ()?

Как бы вы подсчитали количество бит, установленных в числе с плавающей запятой?

Как вы подсчитываете количество бит, установленных в числе с плавающей запятой, с помощью функций 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; } 

Если вы хотите работать с фактическим поразрядным представлением числа с плавающей запятой, вы должны сделать что-то вроде этого:

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

Это означает, что адрес f с адресом оператора & . Этот адрес имеет тип float * , указатель на float. Затем он обновляет его с помощью (int *) , в котором говорится: «Притворяйтесь, что этот указатель больше не указывает на float , но теперь он указывает на int ». Обратите внимание, что он не изменяет значение в f вообще. Затем последний * (или, во-первых, поскольку мы читаем справа налево) разыскивает этот указатель, который является указателем на int , и поэтому возвращает int , aka integer с тем же поразрядным представлением, что и float.

Чтобы сделать обратное (конвертировать и int i обратно в float f ), сделайте противоположное:

 f = *(float *)&i; 

Если я ошибаюсь, эта операция не определена стандартом C, но, вероятно, будет работать на большинстве компьютеров и компиляторов. Он неопределен, потому что я считаю, что фактическое число чисел с плавающей запятой зависит от реализации и может быть оставлено на CPU или компиляторе, и поэтому значение i почти невозможно предсказать после этой операции (то же самое касается значения of f в обратной операции). Это classно используется в функции обратного квадратного корня Джона Кармака для той же гнусной цели.

В любом случае, если вы делаете это в реальном коде, вы должны, вероятно, остановиться и подумать дважды о том, что вы пытаетесь сделать, и о том, почему вы используете float s для этого. Однако, если вы просто делаете это из любопытства, или вы подумали об этом и уверены в своем дизайне и методах, пойдите для этого.

Я убежден, что вы уже знаете, как подсчитать количество бит, заданных в регулярном целое, поскольку это намного проще. Если вы не знаете, ваш компилятор (или язык C, я даже не знаю) может иметь функцию для подсчета бит, или вы можете использовать что-то с замечательного веб-сайта Bit-Twiddling Hacks , который имеет способы делать что-то например, с побитовыми операциями (что должно быть довольно быстро).

Хорошая функция для подсчета заданных битов в целое число, указанное первым ответом:

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

Вы имеете в виду биты, установленные в одноточном представлении IEEE-754 числа? Если это так, добавьте его в int (как float, так и int шириной 32 бит) и выполните обычное количество бит: 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; }