Вещественный двоичный поиск
Вещественный двоичный поиск — алгоритм поиска аргумента для заданного значения монотонной вещественной функции.
Содержание
Формулировка задачи
Пусть нам задана монотонная функция. Необходимо найти значение аргумента этой функции, в которой она принимает определенное значение .
Решение задачи
Применим идею двоичного поиска. Выберем такие границы, где значение функции точно больше и точно меньше заданного значения. Выберем значение в середине этого отрезка. Если оно меньше, чем заданное, то сместим левую границу в середину отрезка. В противном случае сместим правую границу. Далее повторим процесс сужения границ. Встает вопрос, когда остановиться. Есть несколько способов сделать это.
Способы закончить поиск
| Способы | Плюсы | Минусы |
|---|---|---|
| 1) Окончание, когда рассматриваемый отрезок станет меньше заданного эпсилон. | Большая точность найденного значения. | Алгоритм может зациклиться. В компьютере мы работаем с конечным числом вещественных чисел. У чисел есть точность. Соответственно при больших значениях функции, длина отрезка может никогда не уменьшиться до заданного значения. |
| 2) Окончание, когда значение функции на концах отрезках различается менее, чем на заданное эпсилон. | В отличие от предыдущего, не зацикливается при больших значениях функции. | Возможна большая погрешность, если функция будет очень медленно возрастать. |
| 3) «Абсолютно точный поиск» Окончание, когда границы отрезка — два соседних по представлению значения в типе данных. Утверждается, что два числа — соседние, если середина их отрезка совпадает или с левой, или с правой границей. |
Максимально возможная точность найденного значения. | Возможно плохое поведение, если искомый аргумент равен 0. |
| 4) «Итеративный способ» Выполнение конечного числа итераций. |
У способа фиксированная погрешность. | Довольно плохая точность, если границы отрезка находятся на большом расстоянии. |
Выбор границы отрезка для поиска
Для начала найдем правую границу. Выберем произвольную положительную точку (например ). Будем удваивать ее до тех пор, пока значение функции в этой точке меньше заданного. Для того, чтобы найти левую границу выберем произвольную отрицательную точку (например ). Будем удваивать ее до тех пор, пока значение в ней будет больше заданного значения.
Псевдокод
findLeft(c)
x = -1;
while f(x) > c
x = x * 2;
return x;
findRight(c)
x = 1;
while f(x) < c
x = x * 2;
return x;
binSearch(c)
left = findLeft(с);
right = findRight(с);
while left < right - eps //Здесь можно использовать другое условие выхода
mid = (left + right) / 2;
if f(mid) == c //**
return mid; //**
else if f(mid) < c
left = mid;
else
right = mid;
return l;
Примеры использования
- Классической задачей на вещественный двоичный поиск является задача поиска корня -ой степени из числа : . При нижней границей для поиска будет , а верхней — .
- Если функция нестрого монотонна, то, убрав из приведенного выше алгоритма строки, отмеченные , мы получим алгоритм, который будет находить такой, что и .
Замечания
- Необходимо отметить, то функция должна быть строго монотонна, если мы ищем конкретный корень и он единственный. Нестрого монотонна, если нам необходимо найти самый левый (правый) аргумент. Если же функция не монотонна, то данный алгоритм не найдет искомый аргумент, либо найдет аргумент, но он не будет единственным.
- Важным отличием от целочисленного поиска является то, что мы передвигаем границу ровно в середину отрезка (), а не со смещением внутрь отрезка ().
