Страницы

Поиск по вопросам

воскресенье, 29 марта 2020 г.

Как понять и решить задание нормализации числа с плавающей точкой?

#математика #числа_с_плавающей_точкой


Есть такое задание в книге Structured Computer Organization в Appendix B. Floating-point
numbers:


  4. The following binary floating-point numbers consist of a sign bit, an excess
64, radix 2 exponent, and a 16-bit fraction. Normalize them.
  
  a. 0 1000000 0001010100000001
  b. 0 0111111 0000001111111111
  c. 0 1000011 1000000000000000  


Мое решение

Я понимаю это задание так:

У нас есть следующий формат: 1 бит знака, 7 бит экспоненты, со смещением 64 и 16-битная
мантисса. 

Нам нужно нормализовать число 0 1000000 0001010100000001, представленное в этом формате.
Число называется нормализованным, если крайний левый бит его мантиссы — это 1. Значит
нам нужно сдвинуть все биты мантиссы влево на 3 бита. Если мы сдвигаем число влево
на три бита, значит умножаем его на 2³. Следовательно, чтобы число не изменилось, нам
нужно уменьшить экспоненту на 3.

Если исходное число (0 1000000 0001010100000001) в десятичный вид, то получим: 

+ 2^(64 - 64) × (2^(-4) + 2^(-6) + 2^(-8) + 2^(-16)) = +1 × 0.0820465087890625 =
+0.0820465087890625


Если перевести это же число, нормализованное мной, (0 0111101 1010100000001000),
то получим: 

+ 2^(61 - 64) × (2^(-1) + 2^(-3) + 2^(-5) + 2^(-13)) = +2^(-3) × 0.6563720703125
= 0.125 × 0.6563720703125 = +0.0820465087890625


Т. е. то же самое число.

Решение автора книги

Решения нашел здесь. Я так понимаю, это официальные ответы, представленные издательством.


  4. To normalize, shift left 1 bit at a time, adding 1 to the exponent at each step,
until the leftmost bit of the fraction is 1. The results are
  
  (a) 0 1000011 1010100000001000
  (b) 0 1000101 1111111111000000
  (c) 0 1000011 1000000000000000
  
  The third one is already normalized.


Решение @avp

Из-за расхождения в моем ответе и ответе автора, решил попросить помощи в чате C, C++:


  …я понимаю этот пример по другому. Задан знак 0 -- положительное, экспонента --
1000000 == 0x40 == 64 (т.е. с учетом смещения 64 это 0) и 16-разрядное целое 0x1501
== 5377.
  Вот его и надо переводить в дробь
  
  @eanmos вообще, ваш взгляд на задачу наверное более правильный (вычесть 3 из экспоненты).
В моей интерпретации сама формулировка задачи выглядит слишком вычурно. И ответ (ответов
в книге я не нашел) в моей интерпретации будет -- прибавить к экспоненте 12 (поскольку
5377 надо для перевода в дробь делить на 4096), что явно не совпадает с ответом о котором
вы спрашиваете.
  
  — @avp


Так какой ответ правильный? Как правильно решить это задание?
    


Ответы

Ответ 1



Вместо того, чтобы дублировать ответ из комментариев, немного распишу, как было бы представлено в IEEE 754 (Double precision) вышеупомянутое число 0.0820465087890625 В двоичном представлении без какого-либо дополнительного кодирования это число выглядит так: 0.00010101000000012 Что соответсвует нормализованному виду 1.0101000000012 × 2-4 тип double содержит такие битовые поля 1 бит - Знак 11 бит - Порядок (со смещением 1023) 52 бита - Мантисса (дробная ee часть) Целая часть мантиссы не записывается в память, дело в том, что числа в IEEE 754 (почти) всегда записываются в нормализованном виде, а значит перед точкой подразумевается единица. Итого получаем: Знак: 02 Порядок: -4 + 1023 = 011111110112 Мантисса: 01010000000100000000000000000000000000000000000000002 Проверить это можно, например, в python import struct value = 0b0_01111111011_0101000000010000000000000000000000000000000000000000 print(struct.unpack('d', struct.pack('q', value))) # (0.0820465087890625,) Так что единственная отличие от вашего решения в том, что порядок на единицу меньше.

Комментариев нет:

Отправить комментарий