Преобразовать 2 байта или 3 байта в число с плавающей запятой в C

#c #floating-point

#c #с плавающей запятой

Вопрос:

Я работаю с протоколом низкого уровня, который имеет высокую скорость передачи данных и поэтому использует 2 или 3 байта для представления a float в зависимости от диапазона числа, чтобы сделать систему более эффективной.

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

Первые 5 байтов в моем буфере: FF-FF-FF-FF-FF

Первые два байта составляют a float t . Следует отметить, что в документации говорится, что байты имеют малый порядковый номер.

Для анализа t я делаю:

 float t = 0;
memcpy(buffer, amp;t, 2);
  

Следующие 3 байта составляют float ax , чтобы проанализировать, что я делаю:

 float ax = 0;
memcpy(buffer 2, amp;ax, 3);
  

Это правильный способ справиться с этим? Сначала я устанавливаю оба t и ax равными нулю на случай, если вокруг будут случайные байты.

Обновить

Документация не очень хороша. Во-первых, они определяют a Float как a 32-bit IEEE 754 floating-point number .

Тогда есть эта цитата:

 To increase efficiency many of the data packets are sent as 24-bit signed integer words 
because 16-bits do not provide the range/precision required for many of the quantities, 
whereas 32-bit precision makes the packet much longer than required.
  

Затем есть таблица, которая определяется t как первые 2 байта буфера. В нем указано, что диапазон равен 0-59.999. В нем явно не указано, что это a Float , я просто делаю это предположение.

Комментарии:

1. Если вы говорите о двоичной половинной точности 16, вы не можете просто скопировать байты в двоичную одинарную точность 32. Вы должны управлять преобразованием. Я никогда не слышал что-то о 3 байтах с плавающей запятой…

2. Я согласен с @LPs здесь. IEEE-754 обычно используется для представления числа с плавающей запятой. Вы не можете просто прочитать младшие n байты числа с плавающей запятой и предположить, что вы выбрали число с x точностью. Для получения дополнительной информации см. thirum.al/2dk4tx9

3. Где-то в спецификации вашего низкоуровневого протокола должен быть определен точный формат этих чисел с плавающей запятой: сколько бит для экспоненты, сколько для мантиссы, как представлены знаки каждого?

4. Что содержат байты? Я никогда не слышал о 3-байтовых числах с плавающей запятой. Это не невозможно сделать, но почти наверняка это очень специфичный для приложения формат. Я использовал 46-битные (да, 46, не опечатка) числа с плавающей запятой, когда мне нужно было выжать максимум из формата хранения на диске, но затем кодирование и декодирование полностью выполнялись вручную путем сдвига битов, и я принимал очень осознанные решения о том, сколько битов мантиссы и экспонентыдля сохранения. Я подозреваю, что здесь происходит что-то подобное. Конечно, в документации должно быть больше, чем просто «3 байта с плавающей запятой».

5. Также часть о том, что оно равно от 0 до 59,999, означает, что это целое число из 2 байт, значения от 0 до 59999 в виде целого числа представляют от 00.000 до 59.999 для рассматриваемого поля (т.е. вы должны сами добавлять десятичный знак, это не число с плавающей запятой). Тот факт, что все это байты 0xFF, вероятно, означает, что ваше чтение не удалось и / или поле не заполнено. Я знаю, что для некоторых из этих полей MCOM GPS установлено значение 0xFF, когда для поля нет допустимых данных.

Ответ №1:

Возможно, у вас неправильные аргументы. Измените следующим образом:

 memcpy (buffer, amp;t, 2);
  

Для

 memcpy (amp;t, buffer, 2);
  

HTH

[редактировать: чтобы разъяснить всем тем людям, которые проголосовали за мой ответ, вопрос действительно содержит неправильные аргументы. Пытается прочитать буфер, но указывает его в качестве места назначения для memcpy]

Комментарии:

1. Не понижающий коэффициент, но копирование байтов из числа с плавающей запятой половинной точности в число с плавающей запятой одинарной точности не работает….

2. @LPs я понимаю, но OP не знает, почему он получает все нули. Пока он на самом деле не прочитает из своего буфера, он не будет знать, почему memcpy не работает для чисел с плавающей запятой.