§ Сдвиг вправо или влево

В компьютере все составлено из нулей и единиц (0 и 1), и потому существуют разные способы представить число, в том числе представить его в целом или дробном виде. Есть общепринятый стандарт, как правильно представлять числа и вот его как раз и будем рассматривать.
Вначале надо сказать, что числа в процессоре всегда целые, да, несмотря на то, что якобы можно их представить в дробном виде. Все равно все числа остаются целыми, хотя и записываются на бумаге как дроби. Допустим, надо представить число 14 в двоичном виде:
1410 = 11102
Теперь разделим это число на 2, и мы получим число 7 в десятичном и 111 в двоичном. Если разделить любое двоичное число на 2, то у него просто срезается справа один разряд. Примеры:
  • 10101 (21) делим на 2, получаем 1010 (10)
  • 10110 (22) делим на 2, получаем 1011 (11)
  • 01101 (13) делим на 2, получаем 0110 (6)
Как можно заметить, при делении на 2 число как будто сдвигается вправо. Это и называется сдвиг вправо. Соответственно, если мы двигаем число влево, то это равносильно умножению на 2.
В десятичной системе работает все точно так же, только делится и умножается на 10:
  • 12125 делим на 10, получаем 1212
  • 52320 делим на 10, получаем 5232
И так далее. Тут работает точно такой же принцип, что и в двоичной системе - срезается один разряд справа, а все остальные двигаются вправо. Вообще можно обобщить для любой разрядности, не только двоичной, но можно и троичной и восьмеричной, и шестнадцатеричной и вообще любой.
Давайте сохраним число, допустим:
1112 делим 2 -> 11.12

§ Дробные двоичные числа

Как мы видим, число зашло в дробь. То есть получилось что 11 это число 3, а 0.1 в двоичном представлении это на самом деле число 0.5 в десятичном. Давайте тогда попробуем разделить число 1 на 2:
  • 1 / 2 = 0.1 (0.5)
  • 0.1 / 2 = 0.01 (0.25)
  • 0.01 / 2 = 0.001 (0.125)
И так далее. Также можно представить числа в виде суммы, к примеру 0.1 (0.5) + 0.01 (0.25) = 0.11 (0.75). Если 0.75 умножить на 4, то получим число 3. Тем самым образом, можно превратить любое дробное число в целое, если сдвинуть влево его несколько раз.
Допустим, надо представить в виде целого следующее число: 1.00101. Для этого необходимо сделать 5 сдвигов влево, а 5 сдвигов вправо равносильно умножению на 32, т.к. 25 = 32. Получаем следующее число 1001012 = 37. Итак, если 37 разделить на 32, то получим 1.15625, иными словами 1.001012 = 1.1562510.
Данное число можно было перевести еще двумя способами, которые конкретно здесь я рассматривать на буду.

§ Нормализация

Если говорить в общем, то существуют числа, которые называются нормализованные, у таких чисел целое число всегда больше 0 и меньше 10, например нормализованное десятичное число может иметь от 1 до 9, а нормализованное двоичное число всегда имеет целое число, равное единице. Оно всегда равно единице и потому его нигде не пишут, ибо это лишняя потеря информации.
Как нормализовать число? Допустим у нас есть число 3552, и его нужно нормализовать:
  • Делим на 10, получаем 355.2
  • Делим на 10, получаем 35.52
  • Делим на 10, получаем 3.552
Все, число нормализовали. Только этого мало. Чтобы восстановить его, нужно знать, сколько раз мы поделили на 10, а именно 3 раза делили, а значит, что:
3.552*103 = 3552
Эти два числа слева и справа идентичны друг другу, но слева нормализованная форма, а справа - обычная десятичная форма. Число 3.552 называется мантисса, 103 показатель степени, а еще у числа есть знак (плюс или минус), в данном случае это знак плюс. В двоичном представлении за плюс берут число 0, за минус число 1.
Ровно тем же самым способом нормализуются двоичные числа, просто там основание степени будет не 10, а 2. Нормализуем число 11011
  • 11011 делим на 2, получаем 1101.1
  • 1101.1 делим на 2, получаем 110.11
  • 110.11 делим на 2, получаем 11.011
  • 11.011 делим на 2, получаем 1.1011
В итоге получается:
1.1011*24 = 11011
Число 1 вначале всегда убирается, не хранится. Это называется "скрытая единица". Ее нет, но она всегда подразумевается, что она есть. Так что ее всегда надо учитывать.

§ Представление


Рассмотрим то, как представляется число float. Картинка взята с Википедии. Всего число занимает 32 бита, или 4 байта, так как 8 бит = 1 байт. Самый старший 31-бит обозначает знак. Для положительных чисел знак равен 0, для отрицательных равен 1.
Поле "порядок" занимает биты от 23 до 30 включительно, а это ровно 8 бит, или 1 байт. Не думаю, что это сделано случайно, поскольку это очень удобно использовать в дальнейшем. Что такое порядок? Это то число раз, которое надо сдвинуть либо влево, либо вправо.
Порядок выполнен весьма оригинально. Если он равен 127 (или 011111112), то тогда считается, что мантиссу не надо домножать ни на что, то есть 127 это возведение 2 в 0 степень (что дает число 1).
  • Если же порядок равен 128, то тогда надо будет сдвинуть мантиссу влево на 1 шаг (то есть умножить на 2)
  • Порядок 129 значит что умножить на 2 надо два раза (то есть 2 сдвига влево), или умножить на 4
  • Порядок 130 — умножить на 8, три сдвига
  • Порядок 255 — сдвиг на 128 разрядов! Это число 2128! Оно по идее просто огромно.
Если же порядок меньше чем 127, то все будет наоборот работать - мантисса начнет сдвигаться вправо, то есть теперь будет не умножение, а деление на 2n.
Мантисса занимает разряды от 0 до 22 включительно (23 разряда) + 1 скрытый разряд, получается 24-битное число. Это число представляется в виде 3 байтов. Можно считать что точность этого числа составляет, так сказать 2-24 без учета порядка. Самое минимальное число, которое можно получить - это 2-126. Казалось бы, почему бы и не меньше, но из-за скрытой единицы получить в нормализованном виде число меньше этого нельзя никак.
Есть особые зарезервированные числа. Если мантисса равна 0 и порядок равен 0, то такое число считается 0. Если же порядок равен 255, то это число считается INF (бесконечность). Это зарезервированные значения. В зависимости от знака может быть минус 0 и минус бесконечность.

§ Примеры

Необходимо к примеру, перевести число 5.25 в float. Первым делом, необходимо найти его нормализованное значение. Для этого представим в двоичном виде 5.25 = 101.01.
Задача в том, чтобы получить нормализованное число, а значит, надо сдвинуть его вправо (разделить на 2):
  • 101.01 делим на 2, получаем 10.101
  • 10.101 делим на 2, получаем 1.0101
Число нормализовали, какой у нее будет порядок? Поскольку 2 раза сдвигали вправо, чтобы выполнить нормализацию числа, то в этом случае порядок будет равен 127 + 2=129, тем самым образом показывая, сколько раз надо сдвинуть влево (умножить на 2), чтобы получить из нормализованного значения то, что мы задали.
Мантисса этого числа записывается в таком виде:
010 1000 0000 0000 0000 0000
  2    8    0    0    0    0
То есть убирается скрытый разряд, а остальные числа уходят в старшие биты. Самый старший бит мантиссы - это первое число после запятой, самый младший разряд мантиссы - это последнее возможное число после запятой.
Итак, мы получили порядок 129 и мантиссу 280000 (шестнадцатеричная).
Поскольку 129 это 100000012 то полностью число будет записано так:
+ порядок  мантисса
0 10000001 01010000000000000000000
0100 0000 1010 1000 0000 0000 0000 0000
   4    0    A    8    0    0    0    0
Можно использовать этот инструмент для проверки и конвертации чисел.
9 фев, 2021
© 2007-2022 Ужас в том, что Алсу летит имбирем