Вещественный двоичный поиск — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
Строка 2: Строка 2:
  
 
== Формулировка задачи ==  
 
== Формулировка задачи ==  
Пусть нам задана монотонная функция. Необходимо найти место, где значение функции становится меньше, чем какое-то заданное значение.
+
Пусть нам задана монотонная функция. Необходимо найти значение (<tex>c</tex>) этой функции в заданной точке (<tex>x</tex>).
<br>
+
 
[[Файл:Functsia.GIF]]
+
[[Файл:Function.png]]
  
 
== Решение задачи ==
 
== Решение задачи ==
Применим идею двоичного поиска. Выберем такие границы, где значение функции точно больше и точно меньше заданного значения. Выберем значение в середине этого отрезка. Если оно меньше, чем заданное, то сместим левую границу. В противном случае сместим правую границу. Далее повторим процесс сужения границ. Встает вопрос, когда остановиться. Есть несколько способов сделать это.
+
Применим идею двоичного поиска. Выберем такие границы, где значение функции точно больше и точно меньше заданного значения. Выберем значение в середине этого отрезка. Если оно меньше, чем заданное, то сместим левую границу в середину отрезка. В противном случае сместим правую границу. Далее повторим процесс сужения границ. Встает вопрос, когда остановиться. Есть несколько способов сделать это.
  
== Выбор границы ==
+
== Способы закончить поиск ==
Для начала найдем правую границу. Выберем произвольную положительную точку (например 1). Будем удваивать ее до тех пор, пока значение функции в этой точке меньше заданного. Для того, чтобы найти левую границу выберем произвольную отрицательную точку. Будем удваивать ее до тех пор, пока значение в ней будет больше заданного значения.
+
* Первый способ заключается в том, чтобы остановиться, когда рассматриваемый отрезок станет меньше заданного эпсилон. Но у этого подхода есть свои плюсы и минусы:
 +
: <tex>\oplus</tex> Алгоритм с большой точностью найдет значение аргумента
  
== Способы закончить поиск ==
+
: <tex>\ominus</tex> Алгоритм может зациклиться. В компьютере мы работаем с конечным числом вещественных чисел. У чисел      есть точность. Соответственно при больших значениях функции, длина отрезка может никогда не уменьшиться до заданного значения
# Первый способ заключается в том, чтобы остановиться, когда рассматриваемый отрезок станет меньше заданного эпсилон. Но у этого подхода есть свои плюсы и минусы:
+
* Второй способ менее точен. Предлагается заканчивать алгоритм, когда значение функции на концах отрезках различается менее, чем на заданное эпсилон.
#* Алгоритм с большой точностью найдет значение аргумента
+
: <tex>\oplus</tex> В отличии от предыдущего, не зацикливается при больших значениях функции.
#* Алгоритм может зациклиться. В компьютере мы работаем с конечным числом вещественных чисел. У чисел      есть точность. Соответственно при больших значениях функции, длина отрезка может никогда не уменьшиться до заданного значения
+
 
# Второй способ менее точен. Предлагается заканчивать алгоритм, когда значение функции на концах отрезках различается менее, чем на заданное эпсилон.
+
: <tex>\ominus</tex> Возможна большая погрешность, если функция будет очень медленно возрастать
#* В отличии от предыдущего, не зацикливается при больших значениях функции.
+
* Абсолютно точный поиск. Вспомним о том, что вещественный числа в компьютере дискретным. Будем завершать поиск, когда границы отрезка - два соседних по представлению значения в типе данных. Утверждается, что два числа - соседние, если середина их отрезка совпадает или с левой, или с правой границей.
#* Возможна большая погрешность, если функция будет очень медленно возрастать
+
: <tex>\ominus</tex> Возможно плохое поведение, если искомый аргумент равен 0.
# Абсолютно точный поиск. Вспомним о том, что вещественный числа в компьютере дискретным. Будем завершать поиск, когда границы отрезка - два соседних по представлению значения в типе данных. Утверждается, что два числа - соседние, если середина их отрезка совпадает или с левой, или с правой границей.
+
* Итеративный способ. В этом способе выполниться только конечное число число итераций.
#* Возможно плохое поведение, если искомый аргумент равен 0.
+
: <tex>\oplus</tex> Плюсом этого способа является фиксированная погрешность.
# Итеративный способ. В этом способе выполниться только конечное число число итераций.
+
 
#* Плюсом этого способа является фиксированная погрешность.
+
== Выбор границы отрезка для поиска==
 +
Для начала найдем правую границу. Выберем произвольную положительную точку (например </tex>1</tex>). Будем удваивать ее до тех пор, пока значение функции в этой точке меньше заданного. Для того, чтобы найти левую границу выберем произвольную отрицательную точку (например <tex>-1</tex>). Будем удваивать ее до тех пор, пока значение в ней будет больше заданного значения.
  
 
== Псевдокод ==
 
== Псевдокод ==
Строка 46: Строка 48:
 
         mid = (left + right) / 2;
 
         mid = (left + right) / 2;
 
         if f(mid) < c
 
         if f(mid) < c
             l = mid;
+
             left = mid;
 
         else
 
         else
             r = mid;
+
             right = mid;
 
     return l;
 
     return l;
 
</pre>
 
</pre>
 +
== Пример использования ==
 +
Классической задачей на вещественный двоичный поиск является задача поиска корня <tex>n</tex>-ой степени из числа <tex>x</tex>: <tex>\sqrt[n]{x}</tex>. При <tex>x >= 1</tex> нижней границей для поиска будет <tex>1</tex>, а верхней - <tex>x</tex>.
 
== Источники ==  
 
== Источники ==  
 
* [http://www.intuit.ru/department/algorithms/basicalgos/2/ Интернет университет, лекция сортировка и поиск]
 
* [http://www.intuit.ru/department/algorithms/basicalgos/2/ Интернет университет, лекция сортировка и поиск]

Версия 20:34, 12 июня 2012

Вещественный двоичный поиск - алгоритм поиска аргумента для заданного значения монотонной вещественной функции.

Формулировка задачи

Пусть нам задана монотонная функция. Необходимо найти значение ([math]c[/math]) этой функции в заданной точке ([math]x[/math]).

Function.png

Решение задачи

Применим идею двоичного поиска. Выберем такие границы, где значение функции точно больше и точно меньше заданного значения. Выберем значение в середине этого отрезка. Если оно меньше, чем заданное, то сместим левую границу в середину отрезка. В противном случае сместим правую границу. Далее повторим процесс сужения границ. Встает вопрос, когда остановиться. Есть несколько способов сделать это.

Способы закончить поиск

  • Первый способ заключается в том, чтобы остановиться, когда рассматриваемый отрезок станет меньше заданного эпсилон. Но у этого подхода есть свои плюсы и минусы:
[math]\oplus[/math] Алгоритм с большой точностью найдет значение аргумента
[math]\ominus[/math] Алгоритм может зациклиться. В компьютере мы работаем с конечным числом вещественных чисел. У чисел есть точность. Соответственно при больших значениях функции, длина отрезка может никогда не уменьшиться до заданного значения
  • Второй способ менее точен. Предлагается заканчивать алгоритм, когда значение функции на концах отрезках различается менее, чем на заданное эпсилон.
[math]\oplus[/math] В отличии от предыдущего, не зацикливается при больших значениях функции.
[math]\ominus[/math] Возможна большая погрешность, если функция будет очень медленно возрастать
  • Абсолютно точный поиск. Вспомним о том, что вещественный числа в компьютере дискретным. Будем завершать поиск, когда границы отрезка - два соседних по представлению значения в типе данных. Утверждается, что два числа - соседние, если середина их отрезка совпадает или с левой, или с правой границей.
[math]\ominus[/math] Возможно плохое поведение, если искомый аргумент равен 0.
  • Итеративный способ. В этом способе выполниться только конечное число число итераций.
[math]\oplus[/math] Плюсом этого способа является фиксированная погрешность.

Выбор границы отрезка для поиска

Для начала найдем правую границу. Выберем произвольную положительную точку (например </tex>1</tex>). Будем удваивать ее до тех пор, пока значение функции в этой точке меньше заданного. Для того, чтобы найти левую границу выберем произвольную отрицательную точку (например [math]-1[/math]). Будем удваивать ее до тех пор, пока значение в ней будет больше заданного значения.

Псевдокод

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
            left = mid;
        else
            right = mid;
    return l;

Пример использования

Классической задачей на вещественный двоичный поиск является задача поиска корня [math]n[/math]-ой степени из числа [math]x[/math]: [math]\sqrt[n]{x}[/math]. При [math]x \gt = 1[/math] нижней границей для поиска будет [math]1[/math], а верхней - [math]x[/math].

Источники