Будет ли формат с плавающей запятой зависеть от байтов с обратным порядком байтов и байтов с прямым порядком байтов? - PullRequest
12 голосов
/ 09 марта 2011

Я знаю, что целочисленный формат будет различным для машин с прямым порядком байтов и для машин с прямым порядком байтов, то же самое для формата с плавающей точкой (IEEE 754)?

Ответы [ 4 ]

14 голосов
/ 09 марта 2011

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

См. эту статью в Википедии для получения дополнительной информации.

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

Вот предложение о том, как вы можете обрабатывать это переносимым способом, независимо от компилятора Си.Пожалуйста, расцените это как псевдокод, он написан здесь и сейчас в моем веб-браузере и не проверен:

#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;
}
2 голосов
/ 09 марта 2011

Если у вас установлен Linux, у вас, вероятно, будет /usr/include/ieee754.h ... (обратите внимание на #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;
  ...
1 голос
/ 09 марта 2011

Проблемы с порядком байтов возникают, как только вы рассматриваете что-то, состоящее из более мелких единиц. Способ размещения меньших единиц может измениться.

Тогда, если вы заботитесь о вариациях в формате FP, вы должны знать, что IEEE 754 не описывает представление FP (даже если это одна диаграмма предлагает одно), и есть по крайней мере еще один вариант, чем тот, который связан с endianness: бит, обозначающий сигнальные субнормалы, интерпретируется по-разному в разных реализациях.

...