Детали плавающей точки
Автор: FordPerfect
Цель статьи - дать читателю представление о работе с числами с плавающей точкой в программировании. Предполагается дать базовый объём информации и предоставить уровень понимания, достаточный для самостоятельного проведения оценок в задачах, возникающих на практике.
Основная причина создания статьи - наблюдаемый недостаток понимания чисел с плавающей точкой среди программистов - как опасностей так и гарантий. В отсутствие понимания гарантий борьба с опасностями ведётся методами, которые часто можно охарактеризовать как "шаманские".
Второй важной причиной стало отсутствие (насколько мне известно) на русском языке статьи по данному вопросу, сравнимой по полноте изложения с классической статьёй Голдберга. Ближайшая известная альтернатива - всё же намного менее подробна.
Статья может быть использована как учебник или как справочник ("или" - не исключающее).
Статья получилась достаточно объёмной, причём материал структурирован в логической последовательности (для облегчения использования статьи в качестве справочника), а не "от простого к сложному". В связи с этим приношу свои извинения новичкам, желающим краткого введения в работу с числами с плавающей точкой.
В качестве языков примеров используются C/C++.
Все отрывки кода в статье, если явно не оговорено обратное, находятся в общем доступе (public domain).
В статье везде используется термин "числа с плавающей точкой", вместо распространённого в русскоязычной математической литературе "числа с плавающей запятой" (а также - соответствующая типография).
Историческая перспектива
Стандарт IEEE 754
Предмет стандарта
Формат представления
Экспоненциальная запись
Представление чисел с плавающей точкой
Стандартные форматы
Расширенные форматы
Семантика операций
Измерение точности в ULP
Направление округления
Приведение между типами с плавающей точкой
Стандартные арифметические операции
Приведение к целому типу и от целого типа
Приведение к целочисленному значению
Приведение к текстовому виду и из него
Исключения
Реализации
Аппаратная поддержка
x86/x86_64: FPU
x86/x86_64: SIMD
Быстродействие
Порядок байтов (endianness)
Программная поддержка
Стандарты C и C++
Соответствие между C и IEEE754
Компиляторы
Типы
FLT_EVAL_METHOD
Прагмы STDC (FP_CONTRACT/FENV_ACCESS/CX_LIMITED_RANGE)
Преобразование в строки символов и ввод/вывод
Стандартная библиотека
Опции компиляции
Доступ к битовому представлению
Практические примеры
Алгоритм суммирования Кэхена
Double-double
Range reduction
Быстрое преобразование к целому
Быстрый обратный квадратный корень
Задачи для самостоятельного решения
Литература
Историческая перспектива
Рис. 1. Hydrodynamic number-crunching, автор: Guy L. Steele, Jr.
Вычисления с вещественными числами были одним из основных применений компьютеров с момента их появления. Уже механическая машина Z1, построенная в 1938 г. Конрадом Цузе проводила операции с числами с плавающей точкой в формате, удивительно напоминающем современный.
Т. к. множество вещественных чисел бесконечно, в отличие от памяти компьютеров, то формат представления даёт возможность выразить лишь некоторое подмножество вещественных чисел.
Требования к такому подмножеству включают как требования к точности и диапазону, так и сохранение, по возможности, свойств, интуитивно ожидаемых для вещественных чисел.
На протяжении нескольких десятилетий формат чисел с плавающей точкой был индивидуальным для каждого класса машин. Это снижало совместимость и заметно усложняло написание переносимых математических библиотек. Также в таких условиях сложно было получить гарантии точности вычислений (напр. оценить сверху ошибку). Кроме того идиосинкразии конкретных архитектур делали результаты менее интуитивными, иногда - без достаточно веских на то оснований.
Исправить ситуацию был призван стандарт чисел с плавающей точкой IEEE 754.
Процесс стандартизации занял 9 лет (1976-1985), окончательный текст был основан на "K-C-S proposal" (авторы: William Kahan, Jerome Coonen, Harold Stone).
Стандарт предоставил единый для всех систем набор форматов и удивительно высокие гарантии (с т. з. разработчиков реализаций - требования) точности.
Интересующиеся историей принятия стандарта отсылаются к https://www.cs.berkeley.edu/~wkahan/ieee754status/754story.html , как краткому введению.
На данный момент большинство процессоров, вообще поддерживающих вычисления с плавающей точкой, поддерживают именно IEEE 754.
Таким образом, эту часть изначальной задачи стандарта во многом можно считать выполненной.
В 1989 г. Уильям Кэхэн получил премию Тьюринга с формулировкой "for his fundamental contributions to numerical analysis" (рус. "за его фундаментальный вклад в вычислительную математику").
Можно отметить, что, по словам Кэхена, свойства IEEE754 полезны широкой аудитории ("moderately tolerant of well-meaning ignorance among programmers"), а не только (вопреки расхожему мнению) специалистам (у которых обычно больше шансов самостоятельно справиться с идиосинкразиями).
4 мая 2017 (Обновление: 31 дек 2018)