Как вы рассчитываете количество бит, установленных в числе с плавающей запятой, с помощью функций C?Как бы вы подсчитали количество бит, установленных в числе с плавающей запятой?
ответ
Вы имеете в виду биты, установленные в представлении числа одиночной точности IEEE-754? Если это так, добавьте его в int (как float, так и int шириной 32 бит) и выполните обычный бит: SO question #109023.
Кастинг в int будет усекать и конвертировать, а не давать вам необработанное представление. – bdonlan
Хорошая точка. Таким образом, лучшим решением было бы объединение или плавание f; * (int *) & f –
Я думаю, что Адриан имел в виду лить указатель, а не значение. –
Если вы хотите работать на фактическом побитовом представлении числа с плавающей точкой, вы должны сделать что-то вроде этого:
float f; /* whatever your float is */
int i = *(int *)&f;
Что это делает взять адрес f
с адресом-оператора, &
. Этот адрес имеет тип float *
, указатель на поплавок. Затем он обновляет его с помощью (int *)
, в котором говорится: «Притворитесь, что этот указатель больше не указывает на float
, но теперь он указывает на int
». Обратите внимание, что он не меняет значение на f
. Затем последний *
(или, во-первых, поскольку мы читаем справа налево) разыскивает этот указатель, который является указателем на int
и поэтому возвращает int
, a.k.a. целое число с тем же поразрядным представлением, что и float.
Чтобы сделать наоборот (конвертировать и int i
обратно в float f
), сделайте наоборот:
f = *(float *)&i;
Если я не ошибаюсь, эта операция не определено стандартом C, но вероятно, будет работать на большинстве компьютеров и компиляторы. Он неопределен, потому что я считаю, что фактическое число чисел с плавающей запятой зависит от реализации и может быть оставлено в ЦП или компиляторе, и поэтому значение i
почти невозможно предсказать после этой операции (то же самое касается значения f
в обратном порядке). Это классно используется в функции обратного квадратного корня Джона Кармака для той же гнусной цели.
В любом случае, если вы делаете это в реальном коде, вы должны, вероятно, остановиться и подумать дважды о том, что вы пытаетесь сделать, и почему вы используете float
s для этого. Однако, если вы просто делаете это из любопытства, или вы подумали об этом и уверены в своем дизайне и методах, пойдите для этого.
Я убежден, что вы уже знаете, как подсчитать количество бит, заданных в правильном целое, поскольку это намного проще. Если вы не знаете, ваш компилятор (или язык C, я даже не знаю) может иметь функцию для подсчета бит, или вы можете использовать что-то с замечательного веб-сайта Bit-Twiddling Hacks, который имеет способы сделать что-то подобное побитовые операции (которые должны быть довольно быстрыми).
Это не определено не только из-за этого - GCC (в некоторых конфигурациях) будет предупреждать ** разыменованный тип-караульный указатель будет нарушать правила строгого сглаживания ** с серьезной причиной, так как это действительно нарушает предположение (из ISO C, который приносит пользу производительность), что два указателя на отдельные простые типы (кроме символа) никогда не указывают на один и тот же объект. – ephemient
Где находятся два указателя? – sigjuice
'& f' и' (int *) & f' – ephemient
#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;
}
Я забыл про профсоюз! Но вы должны использовать sizeof (float) вместо sizeof (int). Кроме того, int и float имеют одинаковый размер для большинства систем, но я не могу найти никаких стандартов, говорящих о их относительных размерах (или о размерах поплавка), поэтому я не могу быть уверенным - но не было бы лучше имеет только 1 цикл for() и вместо этого использует объединение float и int? –
Это то, что я считаю реалистичным, они почти всегда одинаковы, но я не знаю ни одного стандарта, который диктует это, поэтому я сделал это так. Я мог бы сжать два цикла, выполнив 'int i; int count = 0; для (i = 0; i <8 * sizeof (float); i ++) {if ((1 << (i% 8)) & focs.cs [i/8]) {count ++; }} ' – rampion
Allthough by this (http://stackoverflow.com/questions/881894/is-char-guaranteed-to-be-exactly-8-bit-long-in-c) Вместо этого я должен использовать' CHAR_BIT' из 8 (хотя я уверен с предположением 'sizeof (char) == 1', так как это по определению). – rampion
Хорошая функция для подсчета установленных битов в целое число упомянутых в первом ответе:
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);
Спасибо всем за поддержку – 2009-07-13 18:47:40
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. Постоянное количество символов в числе с плавающей запятой в bash
- 2. 16 бит с плавающей запятой
- 3. Преобразование с плавающей запятой IEEE 32 бит
- 4. Как бы вы подсчитали вхождения строки в строке (Haskell)
- 5. Как бы вы подсчитали вхождения строки в строку?
- 6. Преобразование с плавающей запятой 32-бит в 16 бит
- 7. C++ Portable Бит-позиционирование с плавающей запятой?
- 8. В JavaScript, как бы вы подсчитали количество раз, когда страница обновляется
- 9. Как вы провоцируете ошибку с плавающей запятой в 32 бита
- 10. Принудительно относительно небольшая погрешность в числе с плавающей запятой
- 11. x64 с плавающей запятой
- 12. Подсчитайте количество цифр числа с плавающей запятой
- 13. точность с плавающей запятой
- 14. десятичная система с плавающей запятой.
- 15. Это 52 или 53 бит точности с плавающей запятой?
- 16. Float24 (24 бит с плавающей запятой) в Hex?
- 17. Разделить число с плавающей запятой
- 18. Умножение с плавающей запятой
- 19. Преобразование 16 бит в 32-нит с плавающей запятой
- 20. IEEE754 Полуточность (16 бит) данных с плавающей запятой в vb.net
- 21. Предполагаемый бит в формате с плавающей запятой IEEE
- 22. Как бы вы реорганизовали этот бит кода?
- 23. Как вы получите следующее значение в последовательности с плавающей запятой?
- 24. Кодирование с плавающей запятой
- 25. Знак числа с плавающей запятой
- 26. XPath с плавающей запятой?
- 27. Как вы справляетесь с проблемами округления с плавающей запятой?
- 28. Число квантования с плавающей запятой от двух до 8 бит
- 29. Как код Java проверяет количество регистров с плавающей запятой?
- 30. Плагин с плавающей запятой
почему вас это волнует? – AShelly
для измерения производительности? –