Побитовое число с плавающей запятой в число Int

Я пытаюсь выяснить алгоритм этого, но все, что я получаю с Google, делает это с помощью кастинга. Мне нужно знать подробности.

Итак, если у нас есть число с плавающей запятой x и мы хотим вернуть его двоичное представление, что нам нужно сделать?

Я знаю, что нам нужно вернуть float, если его NaN или бесконечность, но в противном случае, каковы шаги?

ИЗМЕНИТЬ

Функция принимает беззнаковое целое число, которое будет использоваться, как если бы это было число с плавающей запятой, а затем возвращает целое число, которое представляет собой число. Я не могу использовать приведение, только условные выражения и побитовые операторы.


person Jace    schedule 13.09.2011    source источник
comment
Что вы имеете в виду под двоичным представлением? Например, 2.25, записанное как 10.01, или внутреннее представление числа с плавающей запятой? Внутреннее представление обычно в формате IEEE, т.е. значение равно 1. [мантисса] ^ (показатель степени), и сохраняются только мантисса и показатель степени. Вы можете получить фактические единицы и нули, просто скопировав память в int (или используя объединение) и распечатав int.   -  person Adam    schedule 13.09.2011
comment
@ Адам, это, вероятно, всего лишь небольшая терминологическая ошибка с вашей стороны, но преобразование float в int просто обрезает реальную часть числа. Вам понадобится некоторая (довольно краткая) магия указателя, чтобы получить битовый образец поплавка. Хотя со всем остальным я согласен.   -  person zneak    schedule 13.09.2011
comment
См. stackoverflow.com/questions/2376915/   -  person Alok Singhal    schedule 13.09.2011
comment
По поводу вашего редактирования ... Это не всегда возможно, поскольку число с плавающей запятой может быть не целым. Вы можете уточнить?   -  person Mysticial    schedule 13.09.2011
comment
Если это не целое число, я предполагаю, что это либо NaN, либо бесконечность. В этом случае я возвращаю особую последовательность.   -  person Jace    schedule 13.09.2011
comment
@Jace: Внимательно изучите, как представлена ​​одинарная точность. Посмотрите, где показатель степени, где мантисса. Исходя из этого, вы можете использовать пару масок и битовых сдвигов, чтобы получить свой ответ. Требуется небольшая дополнительная логика, чтобы проверить, является ли число целым или нет.   -  person Mysticial    schedule 13.09.2011
comment
Если это не целое число, я предполагаю, что это либо NaN, либо бесконечность. Так ты никогда не увидишь 2.5?   -  person Keith Thompson    schedule 13.09.2011
comment
Возможный дубликат Преобразование float в int (побитовое) в C   -  person Björn Lindqvist    schedule 21.01.2018


Ответы (3)


В качестве альтернативы используйте объединение:

typedef union 
{
    float f_;
    int   i_;
} FloatBits;

FloatBits fb;

fb.f_ = 1.5;

Затем fb.i_ содержит число с плавающей запятой, отображаемое на int, чтобы разрешить извлечение битов. Опять же, обычные предположения о размере типов - вы можете проверить их с помощью sizeof.

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

person Keith    schedule 13.09.2011
comment
Я не могу использовать языковые конструкции. Мне, вероятно, понадобится цикл while или что-то в этом роде, но я не могу понять это ... - person Jace; 13.09.2011
comment
Хотя большинство компиляторов делают это так, как вы описываете, этот доступ технически является неопределенным поведением. - person Mark Elliot; 13.09.2011
comment
@Mark Elliot: В последних версиях стандарта это НЕ неопределенное поведение, а скорее дает значения, определенные реализацией. Это рекомендуемый способ получить битовый массив поплавка. С другой стороны, достижение того же трюка с помощью приведения указателя технически все еще неверно. - person Dietrich Epp; 13.09.2011
comment
@ Дитрих Эпп. Спасибо за замечание. Я подозревал это, спасибо за подтверждение. Определенная реализация - это все, что нам нужно. - person Keith; 13.09.2011

Число float в языке программирования c соответствует стандарту IEEE для арифметики с плавающей запятой (IEEE 754).

Вы можете преобразовать float в int с помощью кода

int i = *(int *)&f; // f is the float variable you want to convert

А затем интерпретируйте int самостоятельно в соответствии со стандартом IEEE 754.

person Summer_More_More_Tea    schedule 13.09.2011
comment
C не определяет формат с плавающей запятой, который зависит от платформы, хотя почти все современные платформы фактически используют IEEE754. (подробнее) - person Mark Elliot; 13.09.2011
comment
не может использовать явное приведение, а входные данные представляют собой целое число без знака, которое следует рассматривать как число с плавающей запятой. - person Jace; 13.09.2011
comment
@Jace Тогда сконвертируй сам по стандарту. :-) Вы должны убедить себя, что этого можно добиться только с помощью операторов условий и битовых операций. - person Summer_More_More_Tea; 13.09.2011
comment
Это нарушает строгий псевдоним и не рекомендуется. Вместо этого используйте союзы. - person Dietrich Epp; 13.09.2011

Чтобы проверить, представляет ли 32-битное значение NaN, если оно было с плавающей запятой, вы можете проверить, больше ли его беззнаковое значение, чем представление для бесконечности.

int n = 
if((n & 0x7FFFFFFF) > 0x7f800000) // is NaN

Удаление знака требуется, поскольку для NaN может быть установлен бит отрицательного знака, равный 1 (хотя NaN не является положительным или отрицательным).


Если вы хотите узнать, является ли число с плавающей запятой NAN, вы можете использовать

float f = NAN
if (f != f) // is NAN

Сравнивать с бесконечностью

float f = INFINITY;
if (f == INFINITY)
person Peter Lawrey    schedule 13.09.2011
comment
Обратите внимание, что компиляторы могут f != f оптимизировать. - person Matthias; 23.04.2018
comment
@Matthias Только в том случае, если для своей цели f != f ложно для всех значений, которые может иметь float f. Это не относится к компиляторам, которые утверждают, что предоставляют арифметику IEEE 754 (большинство из них), хотя это относится к gcc -ffast-math (который не претендует на предоставление арифметики IEEE 754). - person Pascal Cuoq; 30.04.2018
comment
@PascalCuoq idd. для msvc ++ / fp: быстро. - person Matthias; 30.04.2018