Float32 to Float16 - PullRequest
       1

Float32 to Float16

8 голосов
/ 12 июня 2010

Может ли кто-нибудь объяснить мне, как я преобразовываю 32-разрядное значение с плавающей точкой в ​​16-разрядное значение с плавающей точкой?

(s = знак e = экспонента и m = мантисса)

Если 32-разрядное число с плавающей запятой равно 1s7e24m
И 16-разрядное число с плавающей запятой равна 1s5e10m

Тогда это так же просто, как делать?просто ... так может кто-нибудь сказать мне, что вам НУЖНО сделать?

Редактировать: Я вижу, что у меня неправильный сдвиг экспоненты ... так что ЭТО было бы лучше?

fltInt16 =  (fltInt32 & 0x007FFFFF) >> 13;
fltInt16 |= (fltInt32 & 0x7c000000) >> 13;
fltInt16 |= (fltInt32 & 0x80000000) >> 16;

Я надеюсь, что это правильно.Извиняюсь, если я пропускаю что-то очевидное, что было сказано.В полночь пятницы почти полночь ... так что я не "полностью" трезв;)

Правка 2: Упс.Снова заглянул.Я хочу потерять 3 верхних бита, а не нижние!Так как насчет этого:

fltInt16 =  (fltInt32 & 0x007FFFFF) >> 13;
fltInt16 |= (fltInt32 & 0x0f800000) >> 13;
fltInt16 |= (fltInt32 & 0x80000000) >> 16;

Окончательный код должен быть :

fltInt16    =  ((fltInt32 & 0x7fffffff) >> 13) - (0x38000000 >> 13);
fltInt16    |= ((fltInt32 & 0x80000000) >> 16);

Ответы [ 3 ]

5 голосов
/ 08 апреля 2011

Показатель степени должен быть беспристрастным, зажатым и перекрученным. Это быстрый код, который я использую:

unsigned int fltInt32;
unsigned short fltInt16;

fltInt16 = (fltInt32 >> 31) << 5;
unsigned short tmp = (fltInt32 >> 23) & 0xff;
tmp = (tmp - 0x70) & ((unsigned int)((int)(0x70 - tmp) >> 4) >> 27);
fltInt16 = (fltInt16 | tmp) << 10;
fltInt16 |= (fltInt32 >> 13) & 0x3ff;

Этот код будет еще быстрее с таблицей поиска для показателя степени, но я использую его, потому что он легко адаптируется к рабочему процессу SIMD.

Ограничения реализации:

  • Переполнение значений, которые не могут быть представлены в float16, даст неопределенные значения.
  • Недостающие значения вернут неопределенное значение между 2^-15 и 2^-14 вместо нуля.
  • Денормали дадут неопределенные значения.

Будьте осторожны с денормалами. Если ваша архитектура использует их, они могут значительно замедлить вашу программу.

4 голосов
/ 12 июня 2010

Вот ссылка на статью по IEEE754, в которой приведены схемы битов и смещения.

http://en.wikipedia.org/wiki/IEEE_754-2008

4 голосов
/ 12 июня 2010

Экспоненты в ваших представлениях float32 и float16, вероятно, смещены и смещены по-разному.Чтобы получить фактический показатель степени, вам нужно отменить показатель степени, полученный вами от представления float32, а затем сместить его для представления float16.

Помимо этой детали, я думаю, что это так просто, но явсе еще удивляйтесь представлениям с плавающей точкой время от времени.

РЕДАКТИРОВАТЬ:

  1. Проверять переполнение при работе с экспонентами, пока вы на нем.

  2. Ваш алгоритм немного резко обрезает последние биты богомола, что может быть приемлемым, но вы можете захотеть реализовать, скажем, округление до ближайшего, посмотрев на биты, которыесобирается быть сброшенным."0 ..." -> округлить вниз, "100..001 ..." -> округлить вверх, "100..00" -> округлить до четного.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...