Будет ли формат с плавающей точкой зависеть от big-endian и little endian?
Я знаю, что целочисленный формат будет отличаться между машиной big-endian и машиной little-endian, это то же самое для формата float point (IEEE 754)?
4 ответов
спецификация IEEE754 для чисел с плавающей запятой просто не покрывает проблему endianness. Поэтому числа с плавающей запятой могут использовать разные представления на разных машинах, и теоретически даже возможно, что для двух процессоров целочисленная эндианность одинакова, а плавающая точка различна или наоборот.
посмотреть эта статья в Википедии для получения дополнительной информации.
Если у вас есть окно Linux, у вас, вероятно, будет /usr/include/ieee754.ч... (Примечание #if
s)
...
union ieee754_float
{
float f;
/* This is the IEEE 754 single-precision format. */
struct
{
#if __BYTE_ORDER == __BIG_ENDIAN
unsigned int negative:1;
unsigned int exponent:8;
unsigned int mantissa:23;
#endif /* Big endian. */
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned int mantissa:23;
unsigned int exponent:8;
unsigned int negative:1;
#endif /* Little endian. */
} ieee;
...
проблемы Endianness возникают, как только вы рассматриваете что-то, состоящее из меньших единиц. Способ расположения меньших единиц может измениться.
тогда, если вы заботитесь о вариациях в формате FP, вы должны знать, что IEEE 754 не описывает представление FP (даже если это одна диаграмма предлагает один), и есть по крайней мере еще один вариант, чем тот, который связан с endianness: бит, обозначающий сигнальные субнормалы, интерпретируется по-разному в разных реализация.
вот предложение о том, как вы можете справиться с этим переносным способом независимо от компилятора C. Пожалуйста, расцените это как псевдо-код, он написан здесь и сейчас в моем веб-браузере и не проверял:
#include <stdint.h>
#include <stdio.h>
static uint16_t endian = 0xAABB;
#if ( *(const uint8_t*)&endian == 0xAA )
#define BIG_ENDIAN
#else
#define LITTLE_ENDIAN
#endif
#ifdef BIG_ENDIAN
#define FLOAT_NEGATIVE 0x80000000U
#define FLOAT_EXPONENT 0x7F800000U
#define FLOAT_MANTISSA 0x007FFFFFU
#define SHIFT_NEGATIVE 31U
#define SHIFT_EXPONENT 23U
#define SHIFT_MANTISSA 0U
#elif defined LITTLE_ENDIAN
#define FLOAT_NEGATIVE 0x00000001U
#define FLOAT_EXPONENT 0x000001FEU
#define FLOAT_MANTISSA 0xFFFFFE00U
#define SHIFT_NEGATIVE 0U
#define SHIFT_EXPONENT 1U
#define SHIFT_MANTISSA 9U
#endif
typedef union
{
float as_float;
uint32_t as_int;
} ieee745_t;
uint32_t float_negative (ieee745_t ieee);
uint32_t float_exponent (ieee745_t ieee);
uint32_t float_mantissa (ieee745_t ieee);
uint32_t float_negative (ieee745_t ieee)
{
return (ieee.as_int & FLOAT_NEGATIVE) >> SHIFT_NEGATIVE;
}
uint32_t float_exponent (ieee745_t ieee)
{
return (ieee.as_int & FLOAT_EXPONENT) >> SHIFT_EXPONENT;
}
uint32_t float_mantissa (ieee745_t ieee)
{
return (ieee.as_int & FLOAT_MANTISSA) >> SHIFT_MANTISSA;
}
int main()
{
ieee745_t f = {-1.23f};
printf("%f\n", f.as_float);
printf("Negative:\t%X\n", float_negative(f) );
printf("Exponent:\t%X\n", float_exponent(f) );
printf("Mantissa:\t%X\n", float_mantissa(f) );
getchar();
return 0;
}