|
Иногда бывает необходимо для экономии пропускной способности преобразовать 32-битные значения float в 16-битные данные. Например, когда заранее известно, что 32-битный float содержит значения с точностью не более 16 бит. К сожалению, в ESP-IDF нет встроенной поддержки float16_t. Но есть несколько обходных практических решений.
Для экономии места при передаче данных вы можете использовать 16-битные числа с плавающей запятой, но в ESP-IDF нет встроенной поддержки float16_t. Вот несколько практических решений:
Вариант 1: Прямое масштабирование в целые числа. Это самый простой и эффективный способ. Предположим, изначально было исходное значение:
float valf = 123.45; // 32-битное значение с плавающей запятой.
Если мы заранее знаем, что это значение не превышает 327, то его можно преобразовать в 16-битное значение путем домножения на 100:
// На стороне передачи по радиоканалу: int16_t v16_scaled = (int16_t)(valf * 100); // 123.45 -> 12345
На стороне приема можно получить обратно число float с точностью 0.01 следующим образом:
float v16 = v16_scaled / 100.0f; // 12345 -> 123.45
Плюсы:
- Простота и надежность - Точность до 0.01 (часто такая точность бывает достаточна) - Минимальные накладные расходы
Вариант 2: Использование библиотеки half-precision float. Если вам нужен именно формат IEEE 754 half-precision:
// Подключите библиотеку half (нужно установить отдельно) #include "half.hpp" // https://github.com/eliasdaler/half
half_float::half v16; // 2 байта
На ESP32 придется реализовать конвертацию вручную или портировать небольшую библиотеку.
Вариант 3: Собственная реализация half-float. Пример минимальной реализации:
// Преобразование float -> 16 бит (упрощенно) uint16_t float_to_float16(float f) { uint32_t f32 = *(uint32_t*)&f; uint16_t f16 = (f32 >> 16) & 0xFFFF; // Берем старшие 16 бит return f16;
}
// Преобразование 16 бит -> float float float16_to_float(uint16_t f16) { uint32_t f32 = ((uint32_t)f16) << 16; // Расширяем до 32 бит return *(float*)&f32;
}
Фактически Вариант 3 это использование чисел с фиксированной запятой (см. [1]).
[Ссылки]
1. AVR - как избавиться от чисел с плавающей точкой. 2. Поддержка традиционных типов с фиксированной точкой в VisualDSP++. |