FENV(3)

ИМЯ
feclearexcept, fegetexceptflag, feraiseexcept, fesetexceptflag, fetestexcept, fegetenv, fegetround, feholdexcept, fesetround, fesetenv, feupdateenv, feenableexcept, fedisableexcept, fegetexcept - округление и обработка ошибок для чисел с плавающей запятой

ОБЗОР
#include <fenv.h>

int feclearexcept(int excepts);
int fegetexceptflag(fexcept_t *flagp, int excepts);
int feraiseexcept(int excepts);
int fesetexceptflag(const fexcept_t *flagp, int excepts);
int fetestexcept(int excepts);

int fegetround(void);
int fesetround(int rounding_mode);

int fegetenv(fenv_t *envp);
int feholdexcept(fenv_t *envp);
int fesetenv(const fenv_t *envp);
int feupdateenv(const fenv_t *envp);

Компонуется при указании параметра -lm.

ОПИСАНИЕ
Эти одиннадцать функций определены в C99, и описывают обработку округления и исключения (переполнение, деление на ноль и т. д.) при работе с числами с плавающей запятой.

  Исключения
Исключение деление-на-ноль (divide-by-zero) возникает, когда результатом операции над конечными числами является бесконечность.

Исключение переполнение (overflow) возникает, когда результат возможно представить в виде числа с плавающей запятой, но он намного больше абсолютного значения самого большого (конечного) представимого числа с плавающей запятой.

Исключение исчерпания(underflow) возникает, когда результат можно представить в виде числа с плавающей запятой, но он меньше абсолютного значения самого малого положительного нормализованного числа с плавающей запятой (и возникает большая потеря точности, если представить его в виде денормализованного числа).

Исключение inexact возникает, когда округлённый результат операции не равен бесконечной точности результата. Оно может произойти при исключении переполнении или исчерпании.

Исключение invalid возникает, когда при операции получается плохо определённый результат (no well-defined result), например, при 0/0 или бесконечность - бесконечность или sqrt(-1).

  Обработка исключений
Исключения представляются двумя способами: в виде одного бита (наличие/отсутствие исключения) и целого числа, где каждый бит соответствует исключению (определяется реализацией), а также структуры скрытого формата, которая может содержать дополнительную информацию об исключении (возможно, адрес в коде, где оно возникло).

Если реализацией поддерживается обработка определённого исключения, то определён соответствующий макрос: FE_DIVBYZERO, FE_INEXACT, FE_INVALID, FE_OVERFLOW, FE_UNDERFLOW. Если таким способом определить соответствующий бит(ы), например, с целочисленным аргументом FE_OVERFLOW|FE_UNDERFLOW, то могут вызываться функции обработки исключений. Могут поддерживаться и другие исключения. Макрос FE_ALL_EXCEPT — это побитовый OR всех бит, соответствующих поддерживаемым исключениям.

Функция feclearexcept() очищает поддерживаемые исключения, указанные битами в аргументе.

Функция fegetexceptflag() сохраняет представление состояния флагов исключения, представленного аргументом excepts в чёрном ящике *flagp.

Функция feraiseexcept() возбуждает поддерживаемые исключения, заданные битами в excepts.

Функция fesetexceptflag() задаёт полное состояние для исключений, представленных в excepts, в значение *flagp. Это значение должно быть получено с помощью вызова fegetexceptflag() с последним аргументом, значение которого содержит все биты в excepts.

Функция fetestexcept() возвращает слово, в котором биты устанавливаются в соответствии с установленными битами в аргументе excepts и для которых установлено соответствующее исключение.

  Режим округления
Режим округления определяет трактовку результата операций с плавающей запятой, если результат не может быть точно представлен в значащей части числа(significand). Могут быть доступны различные режимы округления: округление к ближайшему (по умолчанию), округление в сторону увеличения (round up, к положительной бесконечности), округление в сторону уменьшения (round down, к отрицательной бесконечности) и округление в сторону нуля.

Если в реализации поддерживается получение и установка направления округления, то для них определены соответствующие макросы: FE_TONEAREST, FE_UPWARD, FE_DOWNWARD и FE_TOWARDZERO.

Функция fegetround() возвращает макрос, соответствующий текущему режиму округления.

Функция fesetround() задаёт режим округления в соответствии со значением аргумента и возвращает ноль при успешном выполнении.

В C99 и POSIX.1-2008 в файле <float.h> описан идентификатор FLT_ROUNDS, который определяет используемый реализацией режим поведения для сложения чисел с плавающей запятой. Значениями идентификатора могут быть:

-1  Режим округления не определён.

0   Округление к нулю.

1   Округление к ближайшему числу.

2   Округление в сторону положительной бесконечности.

3   Округление в сторону отрицательной бесконечности.

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

Значение FLT_ROUNDS должно отражать текущий режим округления, который задаётся с помощью fesetround() (но смотрите ДЕФЕКТЫ).

  Окружение плавающей запятой
С полным окружением плавающей запятой, включая режимы управления и флаги состояния, можно работать через скрытый объект с типом fenv_t. Окружение по умолчанию обозначается как FE_DFL_ENV (с типом const fenv_t *). Это окружение задаётся при запуске программы и определено в ISO C; в нём включено округление к ближайшему числу, все исключения сброшены и задан безостановочный режим (продолжать при возникновении исключений).

Функция fegetenv() сохраняет текущее окружение плавающей запятой в объект *envp.

Функция feholdexcept() делает то же самое, затем очищает все флаги исключений и включает безостановочный режим (продолжать при возникновении исключений), если он доступен. При успешном выполнении возвращается ноль.

Функция fesetenv() восстанавливает окружение плавающей запятой из объекта *envp. Данный объект должен быть корректен, например, должен быть получен из вызова fegetenv() или feholdexcept() или равен FE_DFL_ENV. Данный вызов не возбуждает исключения.

Функция feupdateenv() устанавливает окружение плавающей запятой, представленное объектом *envp, за исключением того, что уже возбуждённые исключения не очищаются. После вызова этой функции, возбуждённые исключения будут побитово сложены с установленными ранее в *envp. Как и для предыдущей функции, объект *envp должен быть корректен.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении эти функции возвращают ноль и не ноль при ошибке.

ВЕРСИИ
Эти функции впервые появились в glibc 2.1.

АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).
Интерфейс | Атрибут | Значение
feclearexcept(), fegetexceptflag(), feraiseexcept(), fesetexceptflag(), fetestexcept(), fegetround(), fesetround(), fegetenv(), feholdexcept(), fesetenv(), feupdateenv(), feenableexcept(), fedisableexcept(), fegetexcept() | Безвредность в нитях | MT-Safe

СООТВЕТСТВИЕ СТАНДАРТАМ
IEC 60559 (IEC 559:1989), ANSI/IEEE 854, C99, POSIX.1-2001.

ЗАМЕЧАНИЯ

  Замечания по glibc
Если возможно, библиотека GNU C определяет макрос FE_NOMASK_ENV, представляющий окружение, в котором при каждом возбуждении исключения срабатывает ловушка (trap). Вы можете проверить этот макрос с помощью #ifdef. Он определён, только при определении _GNU_SOURCE. В стандарте C99 нет способа установить отдельные биты в маске плавающей запятой, например, чтобы отловить определённые флаги. Начиная с версии 2.2, в glibc поддерживаются функции feenableexcept() и fedisableexcept(), которые устанавливают отдельные ловушки плавающей запятой, и fegetexcept() для получения состояния.

#define _GNU_SOURCE         /* смотрите feature_test_macros(7) */
#include <fenv.h>

int feenableexcept(int excepts);
int fedisableexcept(int excepts);
int fegetexcept(void);

Функции feenableexcept() и fedisableexcept() включают (отключают) ловушки для каждого исключения, представленного в excepts, и при успешном выполнении возвращают старый набор включённых исключений, и -1 в противном случае. Функция fegetexcept() возвращает набор всех включённых в данных момент исключений.

ДЕФЕКТЫ
В C99 указано, что значение FLT_ROUNDS должно отражать изменения текущего режима округления, устанавливаемого с помощью fesetround(). В настоящее время это не выполняется: значение FLT_ROUNDS всегда равно 1.

СМОТРИТЕ ТАКЖЕ
math_error(7)