Типы с плавающей точкой

Общее представление

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

Числа с плавающей точкой представляют действительные величины в форме, близкой к научной нотации: мантисса умножается на основание в степени экспоненты. В наиболее распространённых реализациях (IEEE 754) основание равно двум, и значение нормализованного числа задаётся формулой (1)s(1.m)2ebias(-1)^{s} (1.m) 2^{e-\text{bias}}.

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

Стандарт IEEE 754 и параметры формата

Современные языки и процессоры обычно используют стандарт IEEE 754, который описывает форматы и поведение при операциях. Формат определяется числом бит в знаке, экспоненте и мантиссе. Смещение экспоненты (bias) рассчитывается по формуле bias=2k11\text{bias}=2^{k-1}-1.

Параметр точности (p) - количество значащих двоичных цифр (битов) мантиссы плюс скрытый ведущий бит для нормализованных чисел. Для IEEE single (32 бита) и double (64 бита) значения точности различаются: psingle=24, pdouble=53p_{\text{single}}=24,\ p_{\text{double}}=53.

Стандарт также задаёт поведение при переполнении, андерфлоу, правила округления и представление специальных значений: ±Inf (бесконечность), NaN (не число), а также поддерживает денормализованные числа для плавного андерфлоу.

Нормализованные и денормализованные числа

Нормализованное число - число, у которого ведущий бит мантиссы равен 1 (в базисе 2): значение вычисляется по общей формуле, где мантисса в диапазоне [1,2). Для нормализованных чисел действует соотношение (1)s(1.m)2ebias(-1)^{s} (1.m) 2^{e-\text{bias}}.

Минимальное положительное нормализованное значение определяется экспонентой, равной минимальному допустимому значению, и выражается как min_normal=21bias\text{min\_normal}=2^{1-\text{bias}}. Когда значение по модулю становится меньше этого порога, в формате появляются денормализованные числа.

Денормализованное (subnormal) число - число, у которого экспонента равна нулю (в битовом поле), и ведущего скрытого единичного бита нет. Его значение задаётся формулой (1)s(0.f)21bias(-1)^{s} (0.f) 2^{1-\text{bias}}. Самая малая ненулевая величина формата называется ''минимальной денормализованной'' и равна min_subnormal=22pbias\text{min\_subnormal}=2^{2-p-\text{bias}}.

Например, представление одного положительного нормального числа в 32-битном формате может выглядеть как 010000010100011000000000000000000\,10000010\,10001100000000000000000. (Схема битов: знак | экспонента | мантисса) {IMAGE_0}

Диапазон, точность и машинный эпсилон

Точность формата характеризуется понятием машинного эпсилона, который даёт порядок относительной погрешности представления. В простом виде машинный эпсилон определяется как ε=21p\varepsilon=2^{1-p} и показывает, на сколько приблизительно относительно истинного значения может отличаться ближайший представимый соседный бит числа порядка единицы.

Диапазон представимых значений зависит от числа бит в экспоненте и bias. Верхняя граница приблизительно равна (2-2^{1-p})×2^{e_{max}}, а нижняя для нормальных чисел определяется формулой, приведённой выше. Для чисел с очень малой абсолютной величиной используются денормалы.

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

Округление и ошибки при вычислениях

IEEE 754 задаёт несколько режимов округления (например, round to nearest even). Округление вводит погрешность, и операции с плавающей точкой чаще всего моделируются через так называемую модель нормального округления: результат операции представим как fl(xy)=(xy)(1+δ),δε\mathrm{fl}(x\circ y)=(x\circ y)(1+\delta),\quad|\delta|\le\varepsilon, где величина δ ограничена машинным эпсилоном ε.

Типичные ошибки включают: накопление погрешности при суммировании большого количества чисел, потерю значащих цифр при вычитании близких по величине чисел, и невозможность точно представить некоторые десятичные дроби в двоичной системе (например, 0.1). Показательный факт: 0.110=0.0001100110011001120.1_{10}=0.00011001100110011\ldots_2.

Ещё один пример проявления ограниченной точности — арифметические тождества, которые в плавающей точке не выполняются на практике. Так, вычисление суммы и сравнение может дать неожиданный результат: 0.1+0.20.30.1+0.2\neq0.3.

Практические примеры преобразований и ошибок

Рассмотрим преобразование десятичного числа в двоичную форму и далее в формат IEEE. Число 12.375_{10} переводится в двоичную запись, и после нормализации получается выражение 12.37510=1100.0112=1.1000112×2312.375_{10}=1100.011_2=1.100011_2\times2^{3}. На его основе формируется экспонента и мантисса в конкретном формате.

При хранении очень больших чисел мелкие добавления могут полностью теряться. Например, при вычислении выражения (1020+1)10200(10^{20}+1)-10^{20}\approx0 маленькая единица теряется из-за масштабного различия — результат может быть равен нулю после выполнения всех шагов из-за округления.

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

Рекомендации для программиста

1) Не сравнивайте числа с плавающей точкой на строгую равенство; вместо этого используйте сравнение с допустимой погрешностью, зависящей от величины чисел и от машинного эпсилона. 2) При суммировании большого количества чисел рассмотрите перестановку по модулю или использование компенсирующих алгоритмов.

3) При необходимости высокой точности используйте форматы с большей мантиссой (double, long double) или библиотеки произвольной точности. 4) Будьте внимательны при преобразованиях из десятичной в двоичную систему и обратно: не все десятичные дроби представимы точно в двоичной форме, что приводит к аккумулируемым ошибкам.

Ключевые идеи: знать структуру формата (знак, экспонента, мантисса), понимать роль bias и p, оценивать машинный эпсилон и предвидеть ситуации потери значащих цифр — это позволит писать более надёжный и стабильный код при работе с вещественными числами.