IEEE плавающий гекс 424ce027 плавать? - PullRequest
1 голос
/ 02 марта 2011

Если у меня есть плавающий гекс IEEE 424ce027, как мне преобразовать его в десятичный?

unsigned char ptr[] = {0x42,0x4c,0xe0,0x27};

как это сделать?

float tmp = 51.218899;

Ответы [ 6 ]

5 голосов
/ 02 марта 2011

Если вы не хотите принимать endian и нарушать всевозможные правила псевдонимов, этот тип работает хорошо:

union IntFloat {
  uint32_t i;
  float f;
};
...
union IntFloat val;
val.i = 0x424ce027;
printf("%f\n", val.f);

Все еще предполагая, что 'float' является 32-битным, а ваша машина IEEE-754 и имеет соответствующий порядковый номер с целыми числами, но мы, вероятно, можем перестать быть педантичными там.

2 голосов
/ 02 марта 2011

Для преобразования целочисленного значения я бы сделал очень похожий на ответ Джона Рипли, но немного другой механизм. Применяются те же предостережения - float и int должны иметь одинаковый размер и порядковый номер, и float должен быть IEEE, если начальное шестнадцатеричное значение должно рассматриваться как IEEE:

float tmp;
unsigned int src = 0x424ce027;
std::memcpy(&tmp, &src, sizeof tmp);

Вы спрашиваете, как преобразовать в число с плавающей запятой, а затем как преобразовать в десятичную. Число с плавающей запятой не десятичное . Чтобы преобразовать число с плавающей точкой в ​​десятичную строку, вам нужно что-то вроде printf("%g", tmp);

Если вы начинаете с массива unsigned char, а не int, то любое прямое копирование из массива требует заполнения массива с тем же порядком байтов, что и на вашей платформе. Ваш массив с прямым порядком байтов, но Intel с прямым порядком байтов. Таким образом, вы можете reverse массив, как в ответе Джона Б., если вы знаете, что порядковый номер вашей платформы противоположен порядковому порядку массива. Если вы знаете, что массив является прямым порядком байтов, и вы не знаете, что такое порядковый номер вашей платформы, вы можете сделать это (предполагая, что в массиве 8 битов на символ):

unsigned int src = 0;
for (int i = 0; i < sizeof src; ++i) {
    src = (src << 8) + ptr[i];
}

Затем продолжайте как прежде.

1 голос
/ 02 марта 2011

Возможно ...

float f = *reinterpret_cast<float*>(ptr);

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

std::reverse(ptr, ptr + 4);
float f = *reinterpret_cast<float*>(ptr);

Возможно, вы захотите использовать sizeof (float) вместо 4 или какой-либо другой способ получить размер. Возможно, вы захотите отменить копию байтов, а не оригинал. Это несколько уродливо, но вы делаете это.

edit : Как указано в комментариях, этот код небезопасен, так как создает два указателя, накладывающих псевдоним на одну и ту же память, но разных типов. Он вполне может работать на конкретном компиляторе и программе, но не гарантируется стандартом.

0 голосов
/ 01 ноября 2013

Единственный переносимый способ - это анализировать битовые комбинации и формировать число с плавающей запятой вручную, наследуя все правила с плавающей запятой ieee-754:

#define BIAS 150
unsigned char ptr[4] = {0x42,0x4c,0xe0,0x27};
// take care of endianness, which may vary between native float and native int
uint32_t tmp = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3];
uint32_t sign = tmp >> 31;
uint32_t exp = (tmp >> 23) & 0xff;
uint32_t mantissa = tmp & ((1 << 23) - 1);
float result;
if (exp > 0)
   mantissa |= (1 << 23);                        // Handle denormals && Inf

// all integers < 16777216 can be represented exactly as a float
// multiply that by a power of two

result = ldexpf((float)mantissa, exp - BIAS);    // in <math.h>

if (exp == 255 && mantissa != 0)  // Produce NaN from Inf-Inf
   result = (result - result);

if (sign) result = -result;       // Flip sign (also handles -0.0f)
0 голосов
/ 01 ноября 2013

без знака char ptr [] = {0x42,0x4c, 0xe0,0x27};

float fTemp;

uint8_t *temp2 = (uint8_t *) &fTemp;
for (int i = 0; i < sizeof(float); i++)
    temp2[i] = ptr[3-i];

std::cout<<"Data1: "<<fTemp;
0 голосов
/ 02 марта 2011

Предупреждение: это не гарантирует работу в ANSI C (числа с плавающей запятой не обязательно должны быть IEEE754).С учетом вышесказанного,

#include <stdint.h>

uint32_t x = 0x424ce027UL;
printf("%f\n", *((float *)&x));

, который дает вывод:

51.218899

...