32-разрядный стандарт IEEE 754 с плавающей запятой одинарной и шестнадцатеричной - PullRequest
0 голосов
/ 01 марта 2019

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

Однако, просматривая рабочий лист, яУчитывая, я столкнулся со следующим вопросом:

Использование 32-разрядного IEEE 754 с плавающей запятой одинарной точности показывает представление -12.13 в шестнадцатеричном.

Я пытался посмотретьна ресурсах у меня есть и до сих пор не могу понять, как ответить на вышеизложенное.Ответ: 0xc142147b .

Редактировать: Извините, что не разъяснил, но я хотел знать, как сделать это вручную, а не кодировать его.

Ответы [ 2 ]

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

Чтобы закодировать плавающее число, мы должны переписать его как (-1) s 2 e 1.m и кодировать различные части в 32 бита следующим образом

enter image description here

(из https://en.wikipedia.org/wiki/Single-precision_floating-point_format)

  • Первый бит - это знак s: 0 для + и 1 для -

  • 8 следующих битов - это сдвинутый показатель степени e + 127

  • 23, последние биты - дробная часть мантиссы (м)

Сложная задача - преобразовать мантиссу в двоичную. Для некоторых чисел это легко. Например, 5,75 = 4 + 1 + 1/2 + 1/4 = 2 2 + 2 0 + 2 -1 + 2 -2 = 101,11 = 1,0111 × 2 2

Для других чисел (как у вас) это сложнее. Решение состоит в том, чтобы умножить число на два, пока мы не найдем целое число или мы не превысим общее количество бит в коде (23 + 1).

Мыможет сделать это для вашего номера:

 12.13 =       12.13 2^-0
       =       24.26 2^-1
       =       48.52 2^-2
       =       97.04 2^-3
       =      194.08 2^-4
       =      388.16 2^-5
       =      776.32 2^-6
       =     1552.64 2^-7
       =     3105.28 2^-8
       =     6210.56 2^-9
       =    12421.12 2^-10
       =    24842.24 2^-11
       =    49684.48 2^-12
       =    99368.96 2^-13
       =   198737.92 2^-14
       =   397475.84 2^-15
       =   794951.69 2^-16
       =  1589903.38 2^-17
       =  3179806.75 2^-18
       =  6359613.50 2^-19
       = 12719227.00 2^-20

Следующая итерация приведет к числу больше 2 ^ 24 (= ~ 16M), и мы можем остановиться.

MantiКод ssa легко (но немного длинен) конвертировать вручную в двоичный файл, используя обычные методы, и его код 0xc2147b.Если мы извлечем ведущий бит в 1 в позиции 2 23 и поместим его слева от «точки», мы получим мантиссу = 1.42147b × 2 23 (где дробная часть ограничена23 бита).Так как нам пришлось умножить на начальное число 2 20 , чтобы получить это значение, мы наконец получили

mant = 1.42147b × 2 3

Таким образом, показатель степени равен 3, а его код равен 3 + 127 = 130

exp = 130 d = 0x82

и так как число отрицательное

sign = 1

Нам осталось только подавить целую часть мантиссы (скрытый бит) и объединить эти числа, чтобы получить окончательное значение0xc142147b

(Конечно, я использовал программу для генерации этих чисел. Если интересно, вот код C)

#include <stdio.h>
int main () {
  float f=-12.13;
  int sign=(f<0.0);
  float fmantissa;
  fmantissa = (f<0.0?-f:f) ; // abs value of f
  int   e = 0 ;              // the raw exponent
  printf("%2.2f = %11.2f 2^-%d\n",f,fmantissa,e);
  while (fmantissa<=(1<<23)){
    e++; fmantissa*=2.0;
    printf("       = %11.2f 2^-%d\n",fmantissa,e);
  }

  // convert to int
  int mantissa=fmantissa;
  //and suppress hidden bit in mantissa
  mantissa &= ~(1<<23) ;

  // coded exponent
  int exp=127-e+23;

  printf("sign: %d exponent: %d mantissa: 1.%x\n",sign, exp, mantissa);
  //final code
  int fltcode = (sign << 31) | (exp << 23) | mantissa;

  printf("0x%x\n",fltcode);
}
0 голосов
/ 01 марта 2019

-12.13 должен быть преобразован в двоичный файл, а затем в гекс.Давайте сделаем это более или менее так, как это делает библиотека glibc , используя только ручку и бумагу и калькулятор Windows.

Удалите знак, но помните, что у нас был один: 12.13

Significand (или мантисса)

Целая часть, 12 проста: C (hex)

Дробная часть, 0.13 немного сложнее.0.13 - это 13/100.Я использую калькулятор Windows (режим программирования, шестнадцатеричный) и сдвигаю 13 (шестнадцатеричный D) на 32 (*) бита влево: D00000000.Разделите это на 100 (hex 64), чтобы получить: 2147AE14 hex.

Так как нам нужно значение ниже 1, мы снова сместимся вправо на 32 бита и получим: 0.2147AE14

Теперь добавьте целую часть слева: C.2147AE14

Нам нужно только 24 бита для мантиссы, поэтому мы округляем: C.2147B -> C2147B

Теперь это должно быть нормализовано, поэтому двоичная точка перемещается на 3 бита влево (но, разумеется, биты остаются прежними).Показатель степени (первоначально равный 0) увеличивается соответственно на 3, поэтому теперь он равен 3.

Теперь можно удалить скрытый бит: 42147B (теперь 23 младших бита)

Этона данный момент можно превратить в 32-битное значение: 0x0042147B

Экспонента и знак

Теперь давайте возьмем экспоненту: 3 + смещение шестнадцатеричного числа 7F = шестнадцатеричное 82 или 1000 0010 двоичный файл.

Добавьте знак слева слева: 1 1000 0010.Перегруппировано: 1100 0001 0 или C10

Конечно, это старшие биты, поэтому мы превращаем это в 0xC1000000 для полных 32 бит

"Бит-или" обе части

0xC100000 | 0x0042147B = 0xC142147B

И это именно то значение, которое вы хотите.


(*) 32 бита, поэтому у меня более чем достаточно битов, чтобы можно было правильно округлить, позже.

...