Вычисление площади фигуры, ограниченной графиком функции

Ключевые слова: программирование, язык программирования, вычисление, площадь, фигура, график, функция, пример, скачать, c++, pascal, visual basic for applications, vba, doc, php, форма, лекции по программированию

Автор: Приходько Максим Александрович

Вычисление значения многочлена может служить отправной точкой для перехода к решению следующей классической задачи программирования - вычислению площади, ограниченной графиком функции и осью абсцисс, или, говоря проще, интеграла.

Как известно из курса школы, понятие площади сложных фигур вводится с помощью приближения этой фигуры прямоугольниками, площадь которых считается просто - ширина * высота.

Пусть требуется вычислить площадь, ограниченную на отрезке [X1, X2] графиком многочлена и осью абсцисс. Алгоритм вычисления площади, естественно, приводит нас к приближенному значению, поэтому говорят о вычислении площади с точностью e, то есть нахождении такого значения S*, которое по модулю отличается от точного значения S меньше, чем на e: |S - S*| < e.

Для вычисления площади отрезок [X1, X2] разбивают на N частей равной длины d:

d = (X2 - X1) / N
На каждом из N полученных отрезков функцию приближают прямоугольником ширины d, высота которого может варьироваться в зависимости от выбранного подхода. Существует как минимум 6 возможных вариантов:
  • высота = значение фунцкии в левой точке
  • высота = значение в правой точке
  • высота = минимум функции на отрезке
  • высота = максимум функции на отрезке
  • высота = значение функции в середине отрезка
  • высота = среднее значение функции (полусумма значений в левом и правом концах отезка)
Для нашей задачи остановимся на последнем варианте. Тогда площадь фигуры будет складываться из площадей N прямоугольников, где площадь прямоугольника с номером k будет равна:

d * ((Pn(X1 + (k - 1)*d) + Pn(X1 + k*d)) / 2)
А площадь всей фигуры будет вычисляться с помощью конечного цикла:

S = 0

For K = 1 To N

S = S + d * ((Pn(X1 + (K - 1)*d) + Pn(X1 + K*d)) / 2)

Next

Задача вычисления площади позволяет наглядно проиллюстрировать понятие функции и ее использование. То, что в задаче о вычислении значения многочлена являлось фактически всей программой, в нашем случае - уже только ее часть, которая используется другим основным модулем. Этот многократно используемый фрагмент кода программы (в рассматриваемом алгоритме вычисление многочлена или любой другой функции производится 4 раза) "выносится" из основного модуля и выделяется в виде отдельной функции:

Function Pn(X As Double) As Double

...

End Function

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

Pn(X1 + (k - 1)*d)
Способность функций возвращать значение после своего выполнения позволяет "вставлять" вызовы функций непосредственно в формулы, где эти значения должны использоваться:

S = S + d * ((Pn(X1 + (K - 1)*d) + Pn(X1 + K*d)) / 2)
Использование функций позволяет не только экономить место, занимаемое текстом программы (а значит и размер результирующего кода и выделяемую программе память). Представим себе, что после написания программы возникла необходимость вычислить площадь под графиком уже другой функции. В этом случае изменения в алгоритм вычисления значения функции пришлось бы вносить во все 4 соответствующих фрагмента. Обычно это приводит к появлению в тексте программы ошибок, которые потом крайне сложно выявить. А если таких фрагмента 124? В этом и заключается главная "сила" функций - гарантия того, что в каждом месте вызова функции выполняется один и тот же фрагмент кода, а при необходимости внесения каких-либо изменений вносить их нужно только в 1 месте - тексте функции, после чего они (эти изменения) автоматически "переносятся" в каждое место вызова функции.

Вернемся к нашему алгоритму. Вычисление площади производится с помощью бесконечного цикла, каждый раз увеличивая число частей, на которые разбивается исходный отрезок, в 2 раза. Условием прекращения работы бесконечного цикла явлется отличие нового значения площади от старого меньше, чем на 2 e. В этом случае среднее значение будет отличаться от точного значения площади меньше, чем на e, то есть являться решением задачи. Для корректной работы такого алгоритма требуется предварительно вычислить значение площади для некоторого разбиения отрезка, в нашем случае на 10 частей:

N = 10

d = (X2 - X1) / N

S = 0

For K = 1 To N

S = S + d * ((Pn(X1 + (K - 1) * d) + Pn(X1 + K * d)) / 2)

Next

S2 = 0

Переменная S хранит новое значение площади, а переменная S2 - старое. Чтобы алгоритм начал свою работу, старое значение должно заведомо отличаться от нового больше, чем на 2 e. Для этого оно устанавливается равным 0, а количество частей, на которое разбивается исходный отрезок, берется достаточно большим, чтобы обеспечить определенную точность вычисления площади и уберечь нас от ситуации, когда первое значение будет близким к 0 (и алгоритм завершит работу), а значение площади на самом деле 0 не равно.

Последним моментом, представляющим интерес, является часто используемый прием "работы с новым и старым значением чего-либо". Напомним, что на первом шаге S хранит "новое" значение площади, а S2 - "старое", равное 0. На каждом следующем шаге в первую очередь в "старое" значение записывается "новое" (S2 = S), только после чего "новое" значение действительно обновляется (S = ...):

Do While (Abs(S2 - S) > 2 * E)

N = N * 2

d = (X2 - X1) / N

S2 = S

S = 0

For K = 1 To N

S = S + d * ((Pn(X1 + (K - 1) * d) + Pn(X1 + K * d)) / 2)

Next

Loop

Полный текст программы на языке VBA выглядит следующим образом:

Function Pn(X As Double) As Double

Dim N As Integer

Dim I As Integer

Dim Y(4) As Double

Dim C(5) As Double

Dim P As Double

N = 4

C(0) = 1.5

C(1) = 2

C(2) = -3

C(3) = -0.75

C(4) = 1.15

Y(0) = X

For I = 1 To N - 1

Y(I) = Y(I - 1) * X

Next

P = C(0)

For I = 1 To N

P = P + C(I) * Y(I - 1)

Next

Pn = P

End Function

Sub integral()

Dim X1 As Double

Dim X2 As Double

Dim N As Integer

Dim K As Integer

Dim d As Double

Dim E As Double

Dim S As Double

Dim S2 As Double

X1 = Val(InputBox("Введите X1"))

X2 = Val(InputBox("Введите X2"))

E = Val(InputBox("Введите точность e"))

N = 10

d = (X2 - X1) / N

S = 0

For K = 1 To N

S = S + d * ((Pn(X1 + (K - 1) * d) + Pn(X1 + K * d)) / 2)

Next

S2 = 0

Do While (Abs(S2 - S) > 2 * E)

N = N * 2

d = (X2 - X1) / N

S2 = S

S = 0

For K = 1 To N

S = S + d * ((Pn(X1 + (K - 1) * d) + Pn(X1 + K * d)) / 2)

Next

Loop

MsgBox ("s = " + Str((S + S2) / 2))

End Sub

Вот как этот код выглядит в редакторе VBA MS Word:

image

Теперь обратимся к сравнению полученного кода с вариантами, написанными на других языках программирования. Алгоритмические идеи, лежащие в основе предложенного способа, мы обсуждать больше не будем, просто приведем окончательный код для сравнения синтаксиса.

C++ (С++ Builder 4.0)

//---------------------------------------------------------------------------

#include

#include "stdio.h"

#include "math.h"

#pragma hdrstop

//---------------------------------------------------------------------------

#pragma argsused

double Pn(double x)

{

int n;

int i;

double y[10];

double c[11];

double p;

n = 4;

c[0] = 1.5;

c[1] = 2;

c[2] = -3;

c[3] = -0.75;

c[4] = 1.15;

y[0] = x;

for(i = 1; i < n; i++)

{

y[i] = y[i - 1] * x;

}

p = c[0];

for(i = 1; i < n + 1; i++)

{

p = p + c[i] * y[i - 1];

}

return p;

}

int main(int argc, char* argv[])

{

float x1;

float x2;

int n;

int k;

double d;

float e;

double s;

double s2;

printf("x1 = ");

scanf("%f", &x1);

printf("x2 = ");

scanf("%f", &x2);

printf("e = ");

scanf("%f", &e);

n = 10;

d = (x2 - x1) / n;

s = 0;

for(k = 1; k < n + 1; k++)

{

s = s + d * ((Pn(x1 + (k - 1) * d) + Pn(x1 + k * d)) / 2);

}

s2 = 0;

while(fabs(s2 - s) > 2 * e)

{

n = n * 2;

d = (x2 - x1) / n;

s2 = s;

s = 0;

for(k = 1; k < n + 1; k++)

{

s = s + d * ((Pn(x1 + (k - 1) * d) + Pn(x1 + k * d)) / 2);

}

}

printf(("s = " + FloatToStr((s + s2)/2)).c_str());

scanf("%f", s);

}

//---------------------------------------------------------------------------

image

Адаптивное тестирование - быстрая и точная оценка персонала