👨💻 Сегодня буду рассказывать вам про хранение памяти в компьютере, как раз это свяжем с проблемой чисел с плавающей точкой, поэтому постарайтесь все внимательно прочитать‼️
⭕️ Для хранения одной ячейки информации в памяти используется байт (8 битов), а не один бит.
В одном байте, как мы знаем 8 бит, но процессор обращается к памяти на уровне байтов. Он может иметь значение 1 или 0. следовательно 1 будет означать передачу тока в транзистор, а 0 – нет. ⭕️ Каждая такая ячейка имеет уникальный адрес, который используется для доступа к данным, хранящимся в этой ячейке. А нужно это для быстрого поиска и использования информации, процессор будет напрямую обращаться к любой ячейке памяти.
Существует формат IEEE 754, который описывает числа с плавающей точкой.
Число с плавающей запятой состоит из набора отдельных разрядов, условно разделенных на знак, порядок и мантиссу.
⭕️ Порядок (экспонента) — отвечает за масштаб числа, сдвигая десятичную точку.
⭕️ Мантисса — содержит значимые цифры числа. Теперь об этом поподробнее.
Итак, возьмем вещественное число 6.25 и переведем его в двоичный код. (Хочу показать как найти мантиссу)
⭕️ Целую часть (6) мы делим на 2, при этом записывая остаток от деления:
6 : 2 = 3[0], 3 : 2 = 1[1], 1 : 2 = 1[1]❗️ (В квадратных скобках остаток от деления). (И получили мы 110, т.к с конца записали)
Дробную часть (0.25) в свою очередь умножаем на 2, при этом, целую часть записываем, а дробную продолжаем умножать: 0.25 * 2 = 0.5 (0 записали, а 0.5 продолжаем умножать на 2, получаем 1 (0.5 x 2 = 1.0), единицу тоже записываем (Записываем не с конца, просто получаем на выходе 01).
🔗Теперь, все как в школе🧑💻: остатки от деления целой частей частей записываем с конца - 110, и дробную, также с конца - получаем 01. Соединяем и получаем 110.01, это наше число 6.25 только в двоичном виде. Если вам не понятен перевод числа, я прикреплю фотки после сообщения, это будет [1] изображение. Так что это за мантисса вообще? ‼️ Ниже будет разбор по фотке, чтобы было понятнее ‼️
⭕️ Мантисса (или дробная часть) — это часть числа, которая определяет его точность. Я уже упомянул стандарт IEEE-754, согласно этому стандарту, двоичное число представляется в виде формулы, где s — знак числа, M — мантисса, B — основание, E — экспонента (порядок, степень двойки).
⭕️ Поскольку мы работаем в двоичном коде, основание равно двум, и формула принимает следующий вид: [2].
Вещественное число мы сохраняем как три отдельных числа: знак, экспоненту и мантиссу, да и все бы хорошо, но количество бит для хранения ограниченно форматом.
👨💻Формат если че это такая структура, которая описывает, как именно должны быть организованны данные. ❗️ Именно формат определяет, сколько битов выделяется для различных частей данных: для мантиссы, знака и порядка(экспоненты).
⭕️ Рассматриваем формат, в котором доступно 32 бита: 1 бит знака, 8 битов для экспоненты и 23 бита для мантиссы. Этот формат называется "одинарной точностью". Также есть формат 'Двойная точность (64 бита)': 1 бит для знака, 11 битов для экспоненты, 52 бита для мантиссы.
⭕️ Дак вот, нам нужно сдвинуть запятую нашего числа с прошлого поста 110.01 влево настолько, пока в целой части не останется единица. При этом, каждый сдвиг увеличивает степень основания (сейчас поясню).
⭕️ На первом этапе у нас число 110.01 * 10 ** 0, все написано по формуле! Десятка в основании, так как это 2 в двоичной степени ⭕️. Следующим этапом будет сдвиг запятой влево, т.е получится 11.001 * 10 ** 1.
⭕️ Ну и последним этапом, 1.1001 * 10 ** 2.
В итоге мы получаем 1.1001 x 2 ** 2. (По сути просто сдвигаем влево и увеличиваем степень нашей '2')
Здесь 1.1001 - это наша мантисса, а поскольку наше число положительное, бит знака будет равен 0.
На этом этапе хочу поблагодарить автора статьи https://struchkov.dev/blog/ru/floating-point-math/, потому что лично я узнал немало нового и делюсь этим с вами.
⭕️ Чтобы дальше получить экспоненту, нам нужно прибавить число 127. То есть было у нас число 1.1001 * 2 ** 2, к этой двойке прибавляем 127
🔗 Под экспоненту в нашем представлении чисел с плавающей запятой выделено 8 бит, что позволяет сохранить 256 различных значений. Но есть проблемка, ведь в нашем представлении не предусмотрено отдельного бита для знака экспоненты.
⭕️ Решением проблемы будет состоять в хранении экспоненты относительно середины доступного диапазона значений, то есть диапазон чисел от 0 до 255, а для 8-битного диапазона этой "серединой" будет число 127 [3] изображение.
⭕️ По итогу, к нашей изначальной степени 2 прибавляем 127 и получаем 129. При преобразовании 129 в двоичную получаем 10000001 - это и будет экспонента.
Мне лично стало интересно почитать и изучить, как это работает в действительности, а не просто 'а нуу, 0.1 + 0.1 не равно 0.2 да и ладно, написано, значит написано'. Спасибо большое автору статьи! Сейчас скину пару изображений ... а продолжение будет совсем скоро.