Восстановите двоичный код IEEE754 с плавающей запятой из целого числа с фиксированной запятой без FPO - PullRequest
0 голосов
/ 03 мая 2020

У меня есть программа, которая использует числа с фиксированной запятой, потому что используемый мной процессор не поддерживает поплавки IEEE754.

Я хорошо справился с первым преобразованием стандартных IEEE754 в фиксированные точки, найдя экспонента, затем смещение числа и т. д. путем ручного доступа к битам упомянутого IEE754, плавающего в памяти. После преобразования я могу выполнять вычисления с фиксированной точкой очень хорошо.

Однако возможно ли восстановить фиксированную точку (скажем, целое число Q15.16) обратно в плавающую точку IEE754 без FPO, чтобы Процессоры с поддержкой IEEE754 / FPO смогут читать его как их собственный тип с плавающей точкой? Является ли где-нибудь код или примеры того, как модуль FPO ЦП фактически выполняет это преобразование в необработанных байтовых манипуляциях, или это просто какая-то черная магия c, которую нельзя сделать в программном обеспечении? Очевидно, я не ищу сверхточного преобразования.

Все ответы, которые я видел до сих пор, используют FPO. например, сначала вычислив 2 ^ (- num_fraction_bits_in_fixed), для которого уже требуется FPO, а затем масштабировав фиксированную точку до этого коэффициента масштабирования.

Редактировать: используя ответ EOF в качестве базовой линии, я смог создать следующий фрагмент кода для восстановления плавающего элемента IEEE754 из целого числа с фиксированной точкой (в этом примере фиксированная точка - это Q31.32, хранящаяся в INT64). В конце я просто обработал случай 0 вручную, так как без него код на самом деле возвращал бы действительно маленькое, но все же ненулевое значение.

Вот код:

static INT32 count_exponent(UINT64 x)
{
    INT32 l = -33;
    for (UINT64 i = 0; i < 64; i++)
    {
        UINT64 test = 1ULL << i;
        if (x >= test)
            l++;
        else
            break;
    }
    return l;
}

UINT32 float_from_fix32(INT64 value)
{
    INT64 original_num = (INT64)value;
    UINT64 sign = 0;
    if (value < 0)
        sign = 1;

    // remove the signed bit if it's set
    INT64 unsigned_ver = value < 0 ? -value : value;

    // calculate mantissa
    int lz = nlz(unsigned_ver);
    UINT64 y = unsigned_ver << (lz + 1);

    // Our fixed-point is 64bits wide. 8 is the exponent bits for IEEE754
    UINT64 mantissa = y >> (33 + 8);

    // get the non-fractal bits, add the exponent bias ( 127 in IEEE754 )
    UINT64 non_fractal = (unsigned_ver >> 32);
    UINT64 exp = count_exponent(unsigned_ver) + 127;

    // construct the final IEEE754 float binary number
    // first add the last 23 bits (mantissa)
    UINT32 ret = mantissa;

    // add exponent
    ret |= (exp << 23);

    // special case of 0
    if(mantissa == 0 && non_fractal == 0)
        ret = 0;

    // add the sign if needed
    if (sign)
        ret |= 0x80000000;

    return ret;
}

1 Ответ

1 голос
/ 03 мая 2020

Без потери общности рассмотрим беззнаковое число с фиксированной запятой x, предполагая (здесь потеря общности), что каждое число в вашем формате с фиксированной запятой (представляемое) нормализовано с плавающей запятой формата с плавающей запятой:

1) Найдите число ведущих нулей n (могут быть специальные инструкции ЦП, чтобы сделать это быстро и без (программного обеспечения) l oop).

2) Сдвиг числа влево (y = x << n+1) (для получения нормализованной мантиссы с плавающей точкой), затем справа (m = y >> (signbit+exponentbits)), это мантисса с плавающей точкой.

3) Возьмите n, вычтите число не -разрядные биты формата с фиксированной запятой, добавьте смещение экспоненты формата с плавающей запятой. Сдвиньте смещенную экспоненту в битовую позицию показателя результата с фиксированной запятой.

4) Если исходное число не было без знака, установите знаковый бит в результате, если число было отрицательным.


a) Если число с фиксированной запятой подписано v, преобразовать в незабитый u и отдельно сохранить знак s (его можно скопировать в бит знака с плавающей запятой). номер напрямую). Вход без знака для вышеуказанного алгоритма будет x = v < 0 ? -u : u.

b) exponentbits зависит от формата числа с плавающей запятой. Для ieee754 32-битный float это 8.

c). Формат с фиксированной запятой обычно представляет число целым числом n бит, которое (концептуально) делится на константа 2^m. Не дробные биты (если таковые имеются) - это биты n - m, если n > m.

d) exponent bias снова описывается форматом с плавающей запятой. Для ieee754 32-битный float смещение составляет 127.

...