Схема Горнера

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

Схе́ма Го́рнера (або правило Горнера, метод Горнера) — алгоритм обчислення значення многочлена, записаного у вигляді суми одночленів, при заданому значенні змінної. Метод Горнера дозволяє знайти корені многочлена, а також обчислити похідні поліному в заданій точці. Схема Горнера також є простим алгоритмом для ділення многочлена на біном у вигляді xc. Метод названо на честь Вільяма Джорджа Горнера.

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

Дано многочлен P(x):

P(x)=a0+a1x+a2x2+a3x3++anxn,ai.

Нехай потрібно обчислити значення даного многочлена при фіксованому значенні x=x0. Представимо многочлен P(x) в такому вигляді:

P(x)=a0+x(a1+x(a2+x(an1+anx))).

Визначимо таку послідовність:

bn=an
bn1=an1+bnx
bi=ai+bi+1x
b0=a0+b1x

Шукане значення P(x0)=b0. Покажемо, що це правильно.

В отриману форму запису P(x) підставимо x=x0 і будемо обчислювати значення виразу, починаючи з внутрішніх дужок. Для цього будемо замінювати підвирази на bi:

P(x0)=a0+x0(a1+x0(a2+x0(an1+anx0)))=a0+x0(a1+x0(a2+x0(bn1)))  =a0+x0(b1)=b0

Використання схеми Горнера для ділення многочлена на біном

При діленні многочлена a0xn+a1xn1++an1x+an на xc отримуємо многочлен b0xn1+b1xn2++bn2x+bn1 з остачею bn.

За такої умови коефіцієнти отриманого многочлена задовольняють рекурентним співвідношенням:

b0=a0, bk=ak+cbk1.

Так само можна визначити кратність кореня (використати схему Горнера для нового полінома).

Так само схему можна використовувати для знаходження коефіцієнтів при розкладу поліному по степенях xc:

P(x)=A0+A1(xc)+A2(xc)2++An(xc)n

Приклади реалізації обчислення значення

C++

/*
 * 6
 * 3
 * 1 3 -2 1 -1 1
 *
 * Відповідь: 439
 */

# include <stdlib.h> /** EXIT_FAILURE **/
# include <iostream>
using namespace std;

int main(int argc, char *argv[])
{
	register unsigned int i;
	unsigned int n;
	cout << "Введіть кількість елементів: ";
	cin >> n;

	if (n < 1 )
	{
		cerr << "Потрібно хоча б два елементи." << endl;
		return EXIT_FAILURE;
	}

	double *a = new double [n];
	double *b = new double [n];

	cout << "Введіть епсилон: ";
	double eps; cin >> eps;

	cout << "Введіть" << n << " вихідний елемент:" << endl;
	for ( i = 0; i < n; i++ ) cin >> a[i];

	cout << endl;

	/* Малюємо верхню рамку */
	for ( i = 0; i < n; i++ ) cout << "+-------"; cout << "+" << endl;

	/* Виводимо вихідні елементи */
	for ( i = 0; i < n; i++ ) cout << "| " << a[i] << "\t"; cout << "|" << endl;

	/* Знову рамка */
	for ( i = 0; i < n; i++ ) cout << "+-------"; cout << "+" << endl;

	/* За умовою, перший елемент b дорівнює першому елементу a */
	b[0] = a[0];
	cout << "| " << *b << "\t";
	for( i = 1; i < n; i++ )
	{
		b[i] = b[i - 1] * eps;
		/* В цьому місці b[i] буде дорівнювати значенню, що записується в другий рядок */
		b[i] += a[i];
		cout << "| " << b[i] << "\t";
	}
	cout << "+" << endl;

	/* І ще одна завершальна рамка */
	for ( i = 0; i < n; i++ ) cout << "+-------"; cout << "+" << endl << endl;
	cout << "Відповідь: " << b[n-1] << endl;

	delete []b;
	delete []a;
	return 0;
}

Див. також

Література

Посилання

Шаблон:Алгебраїчні рівняння (список)