Это мой код. Когда я меняю мантиссу, показатель степени и знак на 23, 8 и 1 соответственно, чтобы представить 32-битное число, мой код работает. Однако когда значения изменяются для представления битового соотношения в соответствии с 16-битным форматом, он не возвращает правильное значение.
#include <stdio.h>
#include <stdlib.h>
typedef union
{
float val;
struct
{
unsigned int mantissa: 10;
unsigned int exponent: 5;
unsigned int sign: 1;
}float16;
}IEEE_FP;
void print(unsigned int val, int num_bits)
{
for(int i = num_bits-1; i >= 0; i--)
{
if ((val>>i)&1){printf("1");}
else{printf("0");}
}
}
void print16(IEEE_FP test)
{
print(test.float16.sign, 1);
print(test.float16.exponent, 5);
print(test.float16.mantissa, 10);
}
int main()
{
IEEE_FP test;
test.val = 0.789;
print16(test);
return EXIT_SUCCESS;
}
Я пытался передать число с плавающей запятой 0,789 и ожидал 0011101001010000, однако мой код печатает 1111101111100111. Есть идеи?
Извините, показатель степени также имеет формат знаковой мантиссы: не является дополнением до 2. бит мс 1=+ve, 0=-ve.
Ваш код print16 может подойти. Однако вам нужен лучший способ проверить это. Вам нужен способ передачи фактических 16-битных тестовых значений. Если ваш компилятор не поддерживает тип float16, лучше всего добавить uint16_t hexval к вашему объединению, а затем передать значения таким образом, например, test.hexval = 0x5044;.
0x5044 должен был дать вам 34.125. Другие тестовые примеры: 0x3c00 → 1.0; 0xc000 → -2,0; 0x3e00 → 1,5; 0x2e66 → 0,1 (приблизительно).





Причина, по которой код работает для 32-битного значения float, заключается в том, что когда значение сохраняется в члене float val объединения, оно сохраняется с использованием представления для 32-битного типа float. (Этот тип представляет собой формат двоичного32 IEEE-754, также называемый IEEE-754 «одинарной точности».) Это представление создается с помощью комбинации аппаратного и программного обеспечения, анализирующего строку 0.789 в исходном коде и преобразующего ее в формат двоичный32.
Объединение работает, потому что битовые поля члена struct объединения используют тот же член, что и член float val объединения. Чтение значений с использованием битовых полей интерпретирует биты как целые числа, а не как двоичные32. Затем, имея эти значения в виде целых чисел, ваша программа может их распечатать. (Кроме того, расположение битовых полей во многом определяется реализацией. Стандарт C обеспечивает гибкость в порядке и выравнивании битовых полей относительно байтов в памяти. Поэтому этот код не является переносимым.)
Когда вы меняете определения битовых полей, чтобы они имели ширину для 16-битного типа с плавающей запятой, в float val ничего не меняется. Те же биты для двоичного файла32 все еще находятся в памяти. Ничто автоматически не изменяет биты в float val на биты 16-битного типа с плавающей запятой вместо битов двоичного типа32.
Чтобы отобразить биты, которые будут представлять значение в 16-битном типе с плавающей запятой, у вас обычно есть два варианта:
float в float val на имя 16-битного типа с плавающей запятой. Это не указано в стандарте C, но ваш компилятор может иметь для этого тип.Дальнейшая информация о том, как это сделать, зависит от обстоятельств. Если это школьное задание, вам следует использовать информацию, полученную на предыдущих уроках. Если нет, то дальнейшие действия зависят от того, почему вы пытаетесь это сделать, должно ли это быть быстро или просто обучающе, должно ли оно быть переносимым или может быть настроено для конкретной реализации C и так далее.
Число с плавающей запятой — 32-битное число. Вы просто берете первые 16 битов в своем союзе. Если вам нужно сжатое представление, вам нужно иметь 13 неизвестных бит мантиссы и извлечь 8-битный компонент, выяснить, каково его значение в дополнении до 2, и представить его в 5 битах.