Союзы в C - обработка float как массива байтов - PullRequest
0 голосов
/ 01 марта 2019

У меня есть настройки объединения для чтения 32-битного значения с плавающей запятой, которое равно 32.0800018310 (двоичный = 100000.0001010001111011).

Теперь я хочу отобразить содержимое с плавающей запятой, используя целочисленный массив, который составляет 12 байтов (8битов на байт).

Однако я получаю следующий вывод:

Display:
236 
81 
0 
66 

Не должен:

  • data_to_send[0] вернуть первые 8 битчисло с плавающей точкой 01111011 (десятичное = 123)
  • data_to_send[1] возвращает следующие 8 битов с плавающей точкой, которое равно 00010100 (десятичное = 20)
  • data_to_send[2] возвращает следующие 8 битчисло с плавающей запятой, равное 100000. (десятичное = 32)
  • data_to_send[3] возвращает следующие 8 битов с плавающей запятой, равное 0. (десятичное = 0)

Также, что происходит с. в числе?Как вы это отображаете?

union
{
  uint8_t  data_to_send[12];
  float    float_value;
} union_var;

union_var.float_value =  32.0800018310 

//display array
 USB.print("Display: ");
USB.printf("%d \n", union_var.data_to_send[0]);
USB.printf("%d \n", union_var.data_to_send[1]);
USB.printf("%d \n", union_var.data_to_send[2]);
USB.printf("%d \n", union_var.data_to_send[3]);

Ответы [ 4 ]

0 голосов
/ 01 марта 2019

значение с плавающей запятой, которое равно 32.0800018310 (двоичный = 100000.0001010001111011).

Вы путаете представление «число с фиксированной точкой» с представлением «число с плавающей точкой».

Число 32.0800018310 имеет двоичное представление 00000000.0100000.00010100.01111011 , если оно хранится как число с фиксированной точкой с коэффициентом масштабирования 2 ^ 16

То есть:

2^16 is 65536

00000000.0100000.00010100.01111011 as normal binary number is  2102395

and

2102395 / 65536 is 32.0800018310

Таким образом, в качестве числа с фиксированной запятой с коэффициентом масштабирования 2 ^ 16 ваше двоичное представление является правильным, но ...

Компьютеры не хранят числа с плавающей запятой в виде чисел с фиксированной запятой.Распространенным способом является использование формата IEEE 754.

Поэтому, когда вы распечатываете число с плавающей запятой в двоичном формате, вы увидите двоичное представление для IEEE 754 вместо ожидаемых значений.

Формат с фиксированной запятой не является частью стандарта C, но естьколичество библиотек с фиксированной запятой C, которые можно загрузить из сети, если вы хотите играть с математикой с фиксированной запятой.

0 голосов
/ 01 марта 2019

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

0 голосов
/ 01 марта 2019

Как оно хранится, зависит от особенностей вашей системы.Но обычно наиболее значимым битом является знак, затем 8-битное смещение экспоненты на 127, затем 21 мантисса, представляющая суммируемые дроби.

#include <stdio.h>
#include <stdint.h>

void main(void){

    int i;
    union
    {
        uint8_t  data_to_send[12];
        float    float_value;
    } union_var;

    union_var.float_value =  32.0800018310;

    unsigned char sign = 43 + ((union_var.data_to_send[3] >> 7) << 1);

    int exponent = ((union_var.data_to_send[3] & 0x7F) << 1) + (union_var.data_to_send[2] >> 7) - 127;

    int mantissa_store = (union_var.data_to_send[2] & 0x7F << 16) + (union_var.data_to_send[1] << 8) + union_var.data_to_send[0];

    double mantissa = 1.0; 
    double part = 0.5;
    for (i=22;i>=0;i--) 
    {
        if (mantissa_store & (1<<i))
        {
            mantissa += part;
        }
        part /= 2;
    }

    printf("Float is: %c 2^%d * %.12f\n",sign,exponent, mantissa);
    printf("Mantissa value: %d\n",mantissa_store);
}

выход:

Float is: + 2^5 * 1.002500057220
Mantissa value: 20972
0 голосов
/ 01 марта 2019

Как хранятся float значения, зависит от архитектуры вашего компьютера.

В настоящее время они почти всегда хранятся в формате IEEE 754 , который сильно отличается от того, как выпредставьте себе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...