Данная статья посвящена детальному разбору числового типа данных 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}

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

\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-знаковой дроби без целой части, умноженной на число 2^(-126).

Также ситуация, когда экспонента равна 00000010, в мантиссе целая часть ещё равна единице, но этого не видно, а когда экспонента равна 00000001, то мантисса идущая после неё уже явно показывает, что эта единица, записанная в конце экспоненты, и является той самой целой частью мантиссы, похожа на то, что мантисса становится 24-битной, в то время как экспонента укорачивается до 7-битного блока.

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

В общем

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

Мой вопрос для читателей

Существует ли такой метод типа данных с плавающей точкой, который занимает не очень много памяти, но способен хранить числа, которые находятся за пределами границ типов данных double и long double?

Комментарии (15)


  1. Zenitchik
    18.10.2025 11:44

    Извини за минус. Мискликнул. Добавил в карму, для компенсации.


    1. Stroy71
      18.10.2025 11:44

      Компенсировал.