Представляет минимальное число fp16 в шестнадцатеричном формате. - PullRequest
0 голосов
/ 22 июня 2019

Мне нужно использовать min_value для float16 в моей программе, но я не хочу явно записывать его в десятичном формате. Я хочу знать, как представить его в шестнадцатеричном формате.

float FP16_MIN = 5.96e-8;

Исходя из полученного мною ответа, шестнадцатеричный код для fp16 мин с денормой: 0001.

Я хочу сделать функцию:

float min = fp16_min(0x1); 

Я нашел похожую функцию в строке 185 из https://eigen.tuxfamily.org/dox/Half_8h_source.html,, но не понял реализацию.

1 Ответ

2 голосов
/ 22 июня 2019

Для FP16 минимальное положительное нормальное значение:

                  1       0
                  5 43210 9876543210
                  S -E5-- ---F10----
          Binary: 0 00001 0000000000
             Hex: 0400
       Precision: HP
            Sign: Positive
        Exponent: -14 (Stored: 1, Bias: 15)
       Hex-float: +0x1p-14
           Value: +6.1035156e-5 (NORMAL)

Минимальное положительное субнормальное значение:

                  1       0
                  5 43210 9876543210
                  S -E5-- ---F10----
          Binary: 0 00000 0000000001
             Hex: 0001
       Precision: HP
            Sign: Positive
        Exponent: -14 (Stored: 0, Bias: 14)
       Hex-float: +0x1p-24
           Value: +5.9604645e-8 (DENORMAL)

Вы можете написать первое как 0x1p-14, а второекак 0x1p-24 в вашей программе.

Если вы хотите преобразовать из базового шестнадцатеричного представления, то обычным трюком является использование объединения в C и memcpy в C ++.Подробности см. В этом ответе: Как кодируется 1 в C / C ++ как число с плавающей запятой (при условии представления IEEE 754 с одинарной точностью)?

Конечно, чтобы сделать это правильно, вам потребуетсябазовый 16-битный тип с плавающей точкой;который обычно недоступен.Итак, вам нужно сначала выяснить, каким будет соответствующий шестнадцатеричный формат в 32-битном формате с одинарной точностью.Для 1p-24 это легко вычислить с одинарной точностью:

                  3  2          1         0
                  1 09876543 21098765432109876543210
                  S ---E8--- ----------F23----------
          Binary: 0 01100111 00000000000000000000000
             Hex: 3380 0000
       Precision: SP
            Sign: Positive
        Exponent: -24 (Stored: 103, Bias: 127)
       Hex-float: +0x1p-24
           Value: +5.9604645e-8 (NORMAL)

Таким образом, соответствующее представление в виде числа с плавающей запятой одинарной точности будет 0x33800000.(Это нетрудно увидеть: смещение для 32-разрядного числа с плавающей запятой равно 127, так что вы просто положили бы 103 в показателе степени, чтобы получить -24. Я надеюсь, что вы можете сделать это легко самостоятельно; если не спросите.)

Теперь вы можете написать:

#include <inttypes.h>
#include <iostream>

int main(void) {
    uint32_t abc = 0x33800000;
    float i;
    std::memcpy(&i, &abc, 4);
    std::cout<< i << std::endl;
    return 0;
}

, который печатает:

5.96046e-08
...