Интервальная арифметика — различия между версиями
Sementry (обсуждение | вклад) м (первая адекватная версия) |
Sementry (обсуждение | вклад) м |
||
Строка 1: | Строка 1: | ||
− | '''Интервальная арифметика''' — | + | '''Интервальная арифметика''' — способ работы с вещественной арифметикой, который для вещественных интервалов определяет операции, аналогичные обычным арифметическим. Этот способ удобен для работы с величинами, значения которых известны только приближённо, то есть определён конечный интервал, в котором эти значения содержатся. |
== Операции над интервалами == | == Операции над интервалами == | ||
Мы будем рассматривать всевозможные конечные вещественные интервалы <tex> [a, b]\ (a \leqslant b) </tex>. Операции над ними определяются следующим образом: | Мы будем рассматривать всевозможные конечные вещественные интервалы <tex> [a, b]\ (a \leqslant b) </tex>. Операции над ними определяются следующим образом: | ||
− | * Сложение: <tex> [a, b] + [c, d] = [a + c, b + d] </tex> | + | * Сложение: <tex> [a, b] + [c, d] = [\lfloor a + c \rfloor, \lceil b + d \rceil] </tex> |
− | * Вычитание: <tex> [a, b] - [c, d] = [a - d, b - c] </tex> | + | * Вычитание: <tex> [a, b] - [c, d] = [\lfloor a - d \rfloor, \lceil b - c \rceil] </tex> |
− | * Умножение: <tex> [a, b] \times [c, d] = [\min(ac, ad, bc, bd), \max(ac, ad, bc, bd)] </tex> | + | * Умножение: <tex> [a, b] \times [c, d] = [\min(\lfloor ac \rfloor, \lfloor ad \rfloor, \lfloor bc \rfloor, \lfloor bd \rfloor), \max(\lceil ac \rceil, \lceil ad \rceil, \lceil bc \rceil, \lceil bd \rceil)] </tex> |
− | * Деление: <tex> [a, b] / [c, d] = [\min(a/c, a/d, b/c, b/d), \max(a/c, a/d, b/c, b/d)] </tex> | + | * Деление: <tex> [a, b] / [c, d] = [\min(\lfloor a/c \rfloor, \lfloor a/d \rfloor, \lfloor b/c \rfloor, \lfloor b/d \rfloor), \max(\lceil a/c \rceil, \lceil a/d \rceil, \lceil b/c \rceil, \lceil b/d \rceil)] </tex> |
Из определения видно, что интервал-сумма содержит всевозможные суммы чисел из интервалов-слагаемых и определяет границы множества таких сумм. Аналогично трактуются прочие действия. Отметим, что операция деления определена только в том случае, когда интервал-делитель не содержит нуля. | Из определения видно, что интервал-сумма содержит всевозможные суммы чисел из интервалов-слагаемых и определяет границы множества таких сумм. Аналогично трактуются прочие действия. Отметим, что операция деления определена только в том случае, когда интервал-делитель не содержит нуля. | ||
Строка 17: | Строка 17: | ||
Допустим, нам нужно точно определить знак некоторого выражения (это может потребоваться, например, при вычислении предиката [[Предикат "левый поворот" |"левый поворот"]]). Будем использовать для его вычисления интервальную арифметику. Все исходные переменные, входящие в него, будут вырожденными интервалами. При выполнении одной из элементарных операций, описанных выше, будем вычислять нижнюю границу с округлением вниз, а верхнюю - с округлением вверх. Из-за погрешностей, возникающих при округлении вещественных чисел, истинные значения операций нам неизвестны, но они обязательно будет содержаться в посчитанных интервалах. Если левая и правая границы интервала для всего выражения оказались одного знака, то и само выражение однозначно будет иметь тот же знак. В противном случае требуются дополнительные действия. | Допустим, нам нужно точно определить знак некоторого выражения (это может потребоваться, например, при вычислении предиката [[Предикат "левый поворот" |"левый поворот"]]). Будем использовать для его вычисления интервальную арифметику. Все исходные переменные, входящие в него, будут вырожденными интервалами. При выполнении одной из элементарных операций, описанных выше, будем вычислять нижнюю границу с округлением вниз, а верхнюю - с округлением вверх. Из-за погрешностей, возникающих при округлении вещественных чисел, истинные значения операций нам неизвестны, но они обязательно будет содержаться в посчитанных интервалах. Если левая и правая границы интервала для всего выражения оказались одного знака, то и само выражение однозначно будет иметь тот же знак. В противном случае требуются дополнительные действия. | ||
− | + | В Visual С++ режим округления и другие настройки вещественной арифметики можно изменить с помощью функции _controlfp (MSDN рекомендует использовать более безопасную версию _controlfp_s). | |
== Проблемы и ограничения == | == Проблемы и ограничения == | ||
− | Переключение режима округления в процессоре является довольно длительной операцией, поэтому, если использовать его в каждой элементарной операции, это может сильно замедлить вычисления. Впрочем, эту проблему можно легко решить. Пусть мы вычисляем операцию <tex>l = a \circ b </tex> | + | Переключение режима округления в процессоре является довольно длительной операцией, поэтому, если использовать его в каждой элементарной операции, это может сильно замедлить вычисления. Впрочем, эту проблему можно легко решить. Пусть мы вычисляем операцию <tex>l = \lfloor a \circ b \rfloor </tex>, тогда <tex> r = \lceil a \circ b \rceil </tex> - можно вычислить, заменив знаки операндов на противоположные и восстановив корректный знак <tex> a \circ b </tex>. Значит, можно включить округление вниз до работы с интервалами и вернуть стандартный режим после нее, тогда много переключений не потребуется. |
Предполагается, что мы можем управлять округлением в операциях над вещественными числами. Стандарт IEEE 754 гарантирует такую возможность, но не все современные языки/архитектуры его выполняют. Например, согласно [http://www.cs.berkeley.edu/~wkahan/JAVAhurt.pdf этому] материалу, вещественная арифметика в Java не соответствует стандарту IEEE 754 (в частности, не позволяет указывать правила округления). Поэтому на Java нельзя реализовать требуемую интервальную арифметику с использованием только примитивных типов double/float. | Предполагается, что мы можем управлять округлением в операциях над вещественными числами. Стандарт IEEE 754 гарантирует такую возможность, но не все современные языки/архитектуры его выполняют. Например, согласно [http://www.cs.berkeley.edu/~wkahan/JAVAhurt.pdf этому] материалу, вещественная арифметика в Java не соответствует стандарту IEEE 754 (в частности, не позволяет указывать правила округления). Поэтому на Java нельзя реализовать требуемую интервальную арифметику с использованием только примитивных типов double/float. |
Версия 03:18, 17 октября 2011
Интервальная арифметика — способ работы с вещественной арифметикой, который для вещественных интервалов определяет операции, аналогичные обычным арифметическим. Этот способ удобен для работы с величинами, значения которых известны только приближённо, то есть определён конечный интервал, в котором эти значения содержатся.
Операции над интервалами
Мы будем рассматривать всевозможные конечные вещественные интервалы
. Операции над ними определяются следующим образом:- Сложение:
- Вычитание:
- Умножение:
- Деление:
Из определения видно, что интервал-сумма содержит всевозможные суммы чисел из интервалов-слагаемых и определяет границы множества таких сумм. Аналогично трактуются прочие действия. Отметим, что операция деления определена только в том случае, когда интервал-делитель не содержит нуля.
Вырожденные интервалы, у которых начало и конец совпадают, можно отождествить с обычными вещественными числами. Для них данные выше определения совпадают с классическими арифметическими действиями.
Применение в вычислительной геометрии
Допустим, нам нужно точно определить знак некоторого выражения (это может потребоваться, например, при вычислении предиката "левый поворот"). Будем использовать для его вычисления интервальную арифметику. Все исходные переменные, входящие в него, будут вырожденными интервалами. При выполнении одной из элементарных операций, описанных выше, будем вычислять нижнюю границу с округлением вниз, а верхнюю - с округлением вверх. Из-за погрешностей, возникающих при округлении вещественных чисел, истинные значения операций нам неизвестны, но они обязательно будет содержаться в посчитанных интервалах. Если левая и правая границы интервала для всего выражения оказались одного знака, то и само выражение однозначно будет иметь тот же знак. В противном случае требуются дополнительные действия.
В Visual С++ режим округления и другие настройки вещественной арифметики можно изменить с помощью функции _controlfp (MSDN рекомендует использовать более безопасную версию _controlfp_s).
Проблемы и ограничения
Переключение режима округления в процессоре является довольно длительной операцией, поэтому, если использовать его в каждой элементарной операции, это может сильно замедлить вычисления. Впрочем, эту проблему можно легко решить. Пусть мы вычисляем операцию
, тогда - можно вычислить, заменив знаки операндов на противоположные и восстановив корректный знак . Значит, можно включить округление вниз до работы с интервалами и вернуть стандартный режим после нее, тогда много переключений не потребуется.Предполагается, что мы можем управлять округлением в операциях над вещественными числами. Стандарт IEEE 754 гарантирует такую возможность, но не все современные языки/архитектуры его выполняют. Например, согласно этому материалу, вещественная арифметика в Java не соответствует стандарту IEEE 754 (в частности, не позволяет указывать правила округления). Поэтому на Java нельзя реализовать требуемую интервальную арифметику с использованием только примитивных типов double/float.