Метод бісекції

Матеріал з testwiki
Версія від 14:47, 6 листопада 2024, створена imported>Igor Yalovecky
(різн.) ← Попередня версія | Поточна версія (різн.) | Новіша версія → (різн.)
Перейти до навігації Перейти до пошуку

Шаблон:Distinguish Шаблон:Distinguish

Метод бісекції або метод поділу відрізка навпіл — найпростіший чисельний метод для вирішення нелінійних рівнянь виду f(x)=0. Передбачається тільки безперервність функції f(x). Пошук ґрунтується на теоремі про проміжні значення.

Обґрунтування

Алгоритм заснований на наступному наслідку з теореми Больцано — Коші: Шаблон:Теорема Таким чином, якщо ми шукаємо нуль, то на кінцях відрізка функція повинна бути протилежних знаків. Розділимо відрізок навпіл і візьмемо ту з половинок, на кінцях якої функція як і раніше приймає значення протилежних знаків. Якщо значення функції в серединній точці виявилося потрібним нулем, то процес завершується.

Точність обчислень задається одним з двох способів:

  1. εf(x) по осі y, що ближче до умови f(x)=0 з опису алгоритму; або
  2. εx, по осі x, що може виявитися зручним в деяких випадках.

Процедуру слід продовжувати до досягнення заданої точності.

Для пошуку довільного значення досить відняти від значення функції шукане значення і шукати нуль функції що вийшла.

Опис алгоритму

Завдання полягає в знаходженні коренів нелінійного рівняння

f(x)=0.(1)

Для початку ітерацій необхідно знати відрізок [xL,xR] значень x, на кінцях якого функція приймає значення протилежних знаків. Протилежність знаків значень функції на кінцях відрізка можна визначити багатьма способами. Один з безлічі цих способів — множення значень функції на кінцях відрізка і визначення знака похідної шляхом порівняння результату множення з нулем:

f(xL)f(xR)<0,(2.1)

в дійсних обчисленнях такий спосіб перевірки протилежності знаків при крутих функціях призводить до передчасного переповнення.

Для усунення переповнення і зменшення витрат часу, тобто для збільшення швидкодії, на деяких програмно-комп'ютерних комплексах протилежність знаків значень функції на кінцях відрізка потрібно визначати за формулою:

sign(f(xL))sign(f(xR)),(2.2)

так як одна операція порівняння двох знаків двох чисел вимагає меншого часу ніж дві операції: множення двох чисел (особливо з плаваючою комою і подвійною довжиною) і порівняння результату з нулем. При даному порівнянні, значення функції f(x) в точках xL і xR можна не обчислювати, досить обчислити тільки знаки функції f(x) в цих точках, що вимагає меншого машинного часу.

З безперервності функції f(x) і умови (2.2) випливає, що на відрізку [xL,xR] існує хоча б один корінь рівняння (в разі не монотонної функції f(x) функція має кілька коренів і метод призводить до знаходження одного з них).

Знайдемо значення x в середині відрізка:

xM=(xL+xR)/2,(3)

в дійсних обчисленнях, для зменшення числа операцій, на початку, поза циклом, обчислюють довжину відрізка за формулою:

xD=(xRxL),

а в циклі обчислюють довжину чергових нових відрізків за формулою: xD=xD/2 і нову середину за формулою:

xM=xL+xD.

Обчислимо значення функції f(xM) в середині відрізка xM:

  • Якщо f(xM)=0 або, в дійсних обчисленнях, |f(xM)|εf(x), де εf(x) — задана точність по осі y, то корінь знайдений.
  • Інакше f(xM)0 або, в дійсних обчисленнях, |f(xM)|>εf(x), то розіб'ємо відрізок [xL,xR] на два рівних відрізка: [xL,xM] і [xM,xR].

Тепер знайдемо новий відрізок, на якому функція змінює знак:

  • Якщо значення функції на кінцях відрізка мають протилежні знаки на лівому відрізку, f(xL)f(xM)<0 або sign(f(xL))sign(f(xM)), то, відповідно, корінь знаходиться всередині лівого відрізка [xL,xM]. Тоді візьмемо лівий відрізок присвоєнням xR=xM, і повторимо описану процедуру до досягнення необхідної точності εf(x) по осі y.
  • Інакше значення функції на кінцях відрізка мають протилежні знаки на правому відрізку, f(xM)f(xR)<0 або sign(f(xM))sign(f(xR)), то, відповідно, корінь знаходиться всередині правого відрізка [xM,xR]. Тоді візьмемо правий відрізок присвоєнням xL=xM, і повторимо описану процедуру до досягнення необхідної точності εf(x) по осі y.

За кількість ітерацій N поділ навпіл здійснюється N раз, тому довжина кінцевого відрізка в 2N разів менше довжини вихідного відрізка.

Існує схожий метод, але з критерієм зупинки обчислень εx по осі x[1], в цьому методі обчислення тривають до тих пір, поки, після чергового поділу навпіл, новий відрізок більше заданої точності по осі x: (xRxL)>εx. У цьому методі відрізок на осі x може досягти заданої величини εx, а значення функцій f(x) (особливо крутих) на осі y можуть дуже далеко стояти від нуля, при пологих же функціях f(x) цей метод призводить до великої кількості зайвих обчислень.

У дискретних функціях xL,xM і xR — це номера елементів масиву, які не можуть бути дробовими, і, в разі другого критерію зупину обчислень, різниця (xRxL) не може бути менше εx=1.

Псевдокод

Нехай

  • xn — початок відрізка по х;
  • xk — кінець відрізка по х;
  • xi — середина відрізка по х;
  • epsy — необхідна точність обчислень по y (задане наближення інтервалу [xn; xk]: xk — xn до нуля).

Тоді алгоритм методу бісекції можна записати в псевдокоді наступним чином:

  1. Початок.
  2.     Введення xn, xk, epsy.
  3.     Якщо F(xn) = 0, то висновок (корінь рівняння — xn).
  4.     Якщо F(xk) = 0, то висновок (корінь рівняння — xk).
  5.     Поки xk — xn > epsy повторювати:
  6.         dx := (xk — xn)/2
  7.         xi := xn + dx;
  8.         якщо sign(F(xn)) ≠ sign(F(xi)), то xk := xi;
  9.         інакше xn := xi.
  10.     кінець повторювати
  11.     Висновок (Знайдено корінь рівняння — xi з точністю по y — epsy).
  12. Кінець.

Пошук значення кореня монотонної дискретної функції

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

Нехай змінні ліваГраниця і праваГраниця містять, відповідно, ліву лівГран и праву правГран межі масиву, в якій знаходиться наближення до кореня. Дослідження починається з розбиття масиву навпіл (на дві частини) шляхом знаходження номера середнього елемента масиву середина .

Якщо знаки значень масиву масив[ліваГраниця] та масив[середина] протилежні, то наближення до кореня шукають в лівій половині масиву, тобто значенням праваГраниця стає середина і на наступній ітерації досліджується тільки ліва половина масиву. Якщо знаки значень масив[ліваГраниця] і масив[середина] однакові, то здійснюється перехід до пошуку наближення до кореня в правій половині масиву, тобто значенням змінної ліваГраниця стає середина і на наступній ітерації досліджується тільки права половина масиву. Т.о., в результаті кожної перевірки область пошуку звужується вдвічі.

Наприклад, якщо довжина масиву дорівнює 1023, то після першого порівняння область звужується до 511 елементів, а після другого — до 255. Т.о. для пошуку наближення до кореня в масиві з 1023 елементів досить 10 проходів (ітерацій).

Псевдокод:[2]

ліваГраниця = лівГран
праваГраниця = правГран
while (праваГраниця - ліваГраниця > 1) {
   довжинаВідрізка = правГран - лівГран
   половинаВідрізка = int(довжинаВідрізка / 2)
   середина = ліваГраниця + половинаВідрізка
   if (sign(масив[ліваГраниця])  sign(масив[середина]))
      праваГраниця = середина
   else
      ліваГраниця = середина
}
printf середина

Див. також

Примітки

Шаблон:Reflist

Джерела

Посилання

Шаблон:Вікіпідручник