javascript

Числовой тип данных с плавающей точкой float IEEE 754

  • воскресенье, 19 октября 2025 г. в 00:00:06
https://habr.com/ru/articles/957822/

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

Что такое тип данных в программировании?

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

Существует две группы типов данных:

  1. Примитивные

  2. Структурированные

Примитивные типы данных делятся на целочисленные, вещественные, символьный, строковый, логический.

Структурированные типы данных устроены гораздо сложнее, они основаны на применении примитивных или других структурированных типов данных, делятся на массивы, классы, словари, структуры.

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

Числовые типы данных с плавающей точкой состоят из трёх частей.

  1. Знак (направление)

  2. Порядок (экспонента)

  3. Мантисса (дробная часть)

Благодаря экспоненте число может быть чрезмерно большим или наоборот микроскопическим. Мантисса играет роль бинарного аппроксимирования дроби, без неё вещественное число будет представляться, как округлённое к бинарной экспоненте с каким-нибудь целым показателем, что очень грубо. Знак показывает направление числа (вектора) на оси. Помимо всего прочего числовые типы данных с плавающей точкой имеют преимущества над целочисленными типами данных, они могут хранить бесконечность или минус бесконечность, а также неопределённость.

Рассмотрим тип данных float стандарта IEEE 754, который весит 32 бита. На знак уходит 1 бит, на порядок 8 бит, а на мантиссу 23. У такого типа данных широкий экспоненциальный диапазон и неплохая точность, позволяющая хранить до 6 точных десятичных знаков после запятой. Чтобы записать числовое значение в тип данных float, нужно провести некоторые манипуляции.

Например, пусть число равно 3,75 — нам нужно сохранить его в формате float. Поэтапно распишу действия.

  1. Число 3,75 можно бинарно разложить на слагаемые, а именно на 2, 1, 1/2 и 1/4, то есть 3.75 = 2+1+\frac{1}{2}+\frac{1}{4}.

  2. Поскольку число 3,75 больше двойки, то его нужно нормализовать так, чтобы наибольшее слагаемое бинарного разложения (а именно двойка) не превышало двойки и не было меньше единицы, другими словами нужно вынести за скобку число 2, и получится 3.75 = 2(1+\frac{1}{2}+\frac{1}{4}+\frac{1}{8}).

  3. После этого нужно представить каждое слагаемое бинарного разложения, кроме единицы, как дробь, где знаменатель это степень двойки, а числитель равен единице, получается следующее 3.75 = 2(1+\frac{1}{2^{1}}+\frac{1}{2^{2}}+\frac{1}{2^{3}}).

  4. Вынесенная двойка за скобки это бинарная экспонента с показателем, равным единице, но в битовой записи экспонента записывается по формуле: N+127 или N+2^{8-1}-1, где N это значение экспоненты в битовой записи; получается, что экспонента в битовой записи равна десятичному числу 128, а записывается, как 10000000.

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

  6. Поскольку число положительное, то значение знакового бита равно нулю. Следовательно полная битовая запись числа 3,75 в формате float такая: 0 10000000 11100000000000000000000, и обычно запись не разделяется пробелами.

В принципе на объяснение этих манипуляций можно было привести несколько формул, но я специально привёл в пример поэтапный процесс кодирования, чтобы было понятно.

Формула для получения десятичной формы бинарной записи экспоненты в типе float: D = B+127или D=B+2^{8-1}-1, где число D это искомая десятичная форма бинарной записи, которую нужно перевести в двоичную форму, а число B есть изначальное значение экспоненты, которое должно быть не больше 127 и не меньше -126.

Расскажу про нюансы хранения чисел подробнее:

  1. Состояние числа "бесконечность" достигается в том случае, если запись экспоненты состоит строго из единиц, а запись мантиссы строго из нулей. Аналогично и с состоянием числа "минус бесконечность", только здесь знаковый бит равен единице.

  2. Состояние числа "неопределённость" достигается в том случае, если запись экспоненты состоит строго из единиц, а запись мантиссы включает хотя бы одну единицу, и неважно чему равен знаковый бит.

  3. Число 0 может быть в двух вариантах, а именно: положительное и отрицательное. На практике это почти одно и то же число, но в битовой записи отличаются состоянием знакового бита.

Также расскажу про диапазон значений типа данных float.

Если использовать предельную (не доходящую до бесконечности) экспоненту 127, то её битовая запись это 11111110, что в два раза меньше условной бесконечности, где само число равно 2^{127}, а чтобы достигнуть максимального по модулю числового значения, нужно заполнить всю мантиссу единицами 0/1 11111110 11111111111111111111111, и тогда получается такое число:

\pm2^{127}\sum_{n=0}^{23} \frac{1}{2^{n}} = \pm2^{127}(2-\frac{1}{2^{23}})\approx \pm2^{128}

Для получения наименьшего по модулю числового значения, нужно заполнить экспоненту нулями, а в мантисса записать только одну единицу и к тому же в самом конце. Наименьшее число равно

\pm\frac{2^{-2^{8-1}+2}}{2^{23}}=\pm\frac{2^{-126}}{2^{23}} = \pm2^{-149}

Почему экспонента равна числу -126, если её битовая запись равна нулю, скажете вы, потому что по формуле 0-127 = -127, а не -126. Ньюанс в том, что если значение экспоненты равно -126, то её битовая запись может быть в двух состояниях: 00000001 и 00000000. А поскольку в мантиссе целая часть не записывается, она включена в неё изначально при условии, если битовая запись экспоненты не равна нулю. Но если битовая запись представляет из себя ст��ого нули, то целая часть отбрасывается, становясь нулём, и заносится в мантиссу, при этом экспонента всё же равна -126, а мантисса играет роль целого 23-битного числа, поделённого на 2^149, или наоборот, мантисса играет роль 23 знаковой бинарной 23-знаковой дроби без целой части, умноженной на число 2^(-126).

Этот тип данных очень широко применяется в музыке, как формат кодирования сэмплов аудиофайлов. За счёт большого числового диапазона сэмпл может иметь чрезвычайные значения амплитуды и следовательно громкости.

В общем

Тип данных float (double и другие варианты кодирования с плавающей точкой) это по истине крутое изобретение в мире информационных технологий, позволяющее хранить что-то грандиозное при небольших затратах памяти.