Как представить число FLOAT в памяти в C - PullRequest
39 голосов
/ 02 августа 2011

Во время чтения урока я натолкнулся на представление числа с плавающей запятой в памяти.В учебнике был пример с числом с плавающей запятой.

   float a=5.2  with below Diagram

enter image description here

Может кто-нибудь сказать, как этот 5.2 преобразуется в двоичный и как он представлен в памяти на приведенной выше диаграмме?

Ответы [ 11 ]

51 голосов
/ 02 августа 2011

Как уже было сказано, 5.2 представлен как знаковый бит, показатель степени и мантисса. Как вы кодируете 5.2?

5 легко:

101. 

Остальные 0,2 равны 1/5, поэтому разделите 1.00000... (гекс) на 5, и вы получите 0.3333333... (гекс).

(За этим можно легче следовать, если учесть на один бит меньше: 0.FFFF... & rarr; F / 5 = 3, поэтому легко увидеть, что 0.FFFF... / 5 = 0.33333.... Этот один пропущенный бит не имеет значения при делении на 5, значит 1.0000... / 5 = 0.3333... тоже).

Это должно дать вам

0.0011001100110011001100110011... 

Добавьте 5, и вы получите

101.00110011001100110011...         exp 0    (== 5.2 * 2^0)

Теперь сдвиньте его вправо (нормализуйте его, то есть убедитесь, что старший бит находится непосредственно перед десятичной запятой) и соответственно отрегулируйте показатель степени:

1.010011001100110011001100110011... exp +2   (== 1.3 * 2^2 == 5.2)

Теперь вам нужно только добавить смещение 127 (т.е. 129 = 0b10000001) к показателю степени и сохранить его:

0 10000001 1010 0110 0110 0110 0110 0110 

Забудьте верхнюю часть 1 мантиссы (которая всегда должна быть 1, за исключением некоторых специальных значений, поэтому она не сохраняется), и вы получите:

01000000 10100110 01100110 01100110

Теперь вам нужно только выбрать маленький или большой порядковый номер.

Это не совсем то, как это работает, но это более или менее то, что происходит, когда число, подобное 5.2, преобразуется в двоичное.

48 голосов
/ 02 августа 2011

Я думаю, что диаграмма не соответствует одному правильному проценту.

Поплавки хранятся в памяти следующим образом:

Они разложены на:

  • знак s (обозначает, положительный или отрицательный) - 1 бит
  • мантисса m (по сути цифры вашего номера - 24 бита
  • экспонента e - 7 бит

Затем вы можете написать любое число x как s * m * 2^e, где ^ обозначает возведение в степень.

5.2 должен быть представлен следующим образом:

0 10000001 01001100110011001100110    
S    E               M

S=0 обозначает, что это положительное число, т.е. s=+1

E следует интерпретировать как число без знака, что означает 129. Обратите внимание, что вы должны вычесть 127 из E, чтобы получить исходную экспоненту e = E - 127 = 2

M должно интерпретироваться следующим образом: оно интерпретируется как число, начинающееся с 1, за которым следует точка (.), а затем цифры после этой точки. Цифры после . - это те, которые фактически закодированы в m. Мы вводим веса для каждой цифры:

bits in M: 0   1    0     0      1       ... 
weight:    0.5 0.25 0.125 0.0625 0.03125 ... (take the half of the previous in each step)

Теперь вы суммируете веса, в которых установлены соответствующие биты. После этого вы добавляете 1 (из-за нормализации в стандарте IEEE вы всегда добавляете 1 для интерпретации M) и получаете оригинал m.

Теперь вы вычисляете x = s * m * 2^e и получаете свой оригинальный номер.

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

0 10000001 01001100110011001100110    
S    E               M

, но скорее наоборот (просто берите 8-битные блоки и отражайте их порядок)

01100110 01100110 10100110 01000000
MMMMMMMM MMMMMMMM EMMMMMMM SEEEEEEE
7 голосов
/ 02 августа 2011

Значение представляется в памяти в обратном порядке, но запутанным моментом может быть то, что 5.2f действительно представляется как 5.1999998 из-за потери точности значений с плавающей запятой.

4 голосов
/ 31 марта 2012

Представление 5.2 очень просто в двоичной логике:

     8 4 2 1
5 -> 0 1 0 1

Для десятичного числа:

Взять .2 и умножить на 2 (поскольку он представлен в двоичном виде). ​​

.2 X 2 = 0.4 -> take the value after the
                decimal point, don't take the value before
                the decimal point

.4 X 2 = 0.8
.8 X 2 = 1.6
.6 X 2 = 1.2
.2 X 2 = 0.4

и так далее ...

После этого шага возьмите значение перед десятичной запятой из выходных данных вышеупомянутых шагов:

.2 X 2 = 0.4 -> take 0 from this for representing in binary form

Таким образом, окончательное значение o / p 5,2:

0101.00110...
3 голосов
/ 02 августа 2011

Сырой поплавок 5,2:

01000000101001100110011001100110
^ sign bit

В памяти, обратный порядок байтов (как ваша диаграмма):

01100110011001101010011001000000
                        ^ sign bit
1 голос
/ 19 августа 2016

5.2 в двоичном виде 101.00110011 ...... ------> ненормализованная форма 5.2 - .10100110011 .... x 2 ^ 3 ------> явная нормальная форма 5.2 - .0100110011 x2 ^ 3 в неявной нормальной форме

здесь знаковый бит становится 0 (потому что число положительное), а показатель степени равен семи битам, поэтому он использует избыточную 64-процентную нотацию, так что показатель степени станет 64 + 3 = 69т. е. 1000101, а остальные будут мантиссой (всего 32 бита - 7 битов экспоненты - 1 бит знака = 24 бита) 0100 1100 1100 1100 1100 1100

В приведенном выше примере символьный бит верен Excess 64 не применяется, поэтому не нормализованный, но в идеале он должен использовать неявную нормализацию части Мантиссы во втором байте, если вы применяете неявную нормализацию, MSB '1' не придет.

1 голос
/ 11 сентября 2014

5.2

Число хранится в форме "Бит знака, Экспонента, Мантиссы". В двоичной форме 5 равно 8 4 2 1, поэтому 0101 и .2 равно

.2*2=.4   0
.4*2=.8   0
.8*2=1.6  1

и бит знака 0, поскольку число положительное.

0 0101 001....
0 голосов
/ 31 октября 2017
int a;
float b=5.2;
memcpy(&a, &b, 4);
printf("%d",a);

Это дает 0100 0000 1010 0110 0110 0110 1000 0001 (1084647041)

0 голосов
/ 02 февраля 2014

Ниже две ссылки действительно помогли мне понять кодировку числа с плавающей точкой IEE 754 в двоичном формате,

http://www.pitt.edu/~juy9/142/slides/L3-FP_Representation.pdf

http://en.wikipedia.org/wiki/Single-precision_floating-point_format

0 голосов
/ 15 августа 2013

Техника конвертации, первоначально размещенная на другом сайте, показывается излишне сложной (хотя она требует правильного ответа).Для представления памяти 5.2 в памяти:

Сначала преобразуйте его в простую двоичную систему, что даст нам 101,001100110011001100110011

Теперь измените его в научную форму: 1.01001100110011001100110011 x 10 ^ 2.

Теперь наш знаковый бит равен 0, поскольку число положительное

Для показателя степени нам нужно (127 + 2) до 8 битов, что дает нам 10000001

Дробь составляет 01001100110011001100110.(23 бита) (исключая первую 1 научную форму)

=> представление:

0 10000001 0100 1100 1100 1100 1100 110

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...