Хранение целых как поплавков - PullRequest
8 голосов
/ 11 ноября 2010

Предположим, у меня есть API, который позволяет мне хранить только числа с плавающей точкой или массивы с плавающей точкой. Однако я хотел бы хранить здесь целочисленные значения.

Я (примерно) понимаю, что у меня все в порядке с прямым броском примерно до 2 ^ 23, но что, если я хочу подняться выше? Можно ли как-нибудь воспользоваться 32-битными числами с плавающей запятой и быть уверенным, что я верну то же число?


Для уточнения:

Я делаю некоторые операции над облаками точек с помощью Pixar PRMan (т.е. RenderMan). Я могу написать на C или C ++ ссылки на предварительно скомпилированный API-интерфейс облака точек. PRMan ни в коем случае не должен использовать эти целые, которые я храню; Мне нужно только вернуть их в целости и сохранности после обработки других данных, прикрепленных к точкам.

Ответы [ 3 ]

9 голосов
/ 11 ноября 2010

Сомнительный:

В C вы можете сделать следующее, что потенциально небезопасно (из-за строгих правил наложения имен):

int i = XXX;
float f;
*(int *)&f = i;

и основывается на предположении, что sizeof(int) == sizeof(float).

Менее сомнительно:

Более безопасным, но более длинным, является следующее:

int i = XXX;
float f;
memcpy(&f, &i, sizeof(int));

Это все еще зависит от соответствия размеров типов данных. Тем не менее, оба из вышеперечисленного предполагают, что внутренняя часть используемой вами библиотеки не будет ничего делать с данными. Например, у него не будет специальной обработки для NaN или +/- бесконечности и т. Д.

Safe:

Если вы будете растрачивать два поплавка на одно целое, вы можете сделать что-то вроде:

.
int i = XXX;
float f[2] = { (i & 0xFFFF), ((unsigned)i >> 16 };

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

4 голосов
/ 11 ноября 2010

Поле мантиссы позволяет хранить 23 бита. Поле экспоненты позволяет хранить почти 8 бит , его ширина 8 бит с несколькими зарезервированными значениями. И есть бит знака.

Избегая зарезервированных значений в показателе степени, вы все равно можете хранить 31 бит по вашему выбору.

Вы можете найти frexp и ldexp полезными.

0 голосов
/ 11 ноября 2010

Все ответы, приведенные здесь, предполагают, что вы хотите использовать только байты, зарезервированные для хранения с плавающей запятой, в качестве места для хранения int. Они не позволят вам выполнять арифметику со значениями типа int-encoded-in-float. Если вы хотите, чтобы арифметика работала, вы застряли с 24,99 бит (т. Е. Диапазон от - (2 ^ 24-1) до (2 ^ 24-1); я считаю бит знака 0,99 бит, а не 1 бит, потому что вы не может хранить минимально возможное значение с представлением знака / величины с плавающей точкой) и разреженный набор больших значений (например, любое 32-битное целое число, кратное 256, может быть представлено в float).

...