|
Занимаясь поверхностным натяжением, я написал довольно полезную программу для Excel VBA, которая вычисляет интеграл от функции, заданной в табличном виде. Идея состояла в том, чтобы интерполировать табличную функцию сплайном и вычислять интеграл уже в аналитическом виде от сплайна. Хочу поделиться с вами этой функцией — может быть пригодится для чего-нибудь.
Вот ее текст на Бейсике (Arg — массив значений аргументов, Fn — массив значений функции, х1 и х2 — нижний и верхний пределы интегрирования, они не должны вылезать за пределы таблицы): ———————————————————————— Function INTEGRAL(Arg, Fn, x1 As Single, x2 As Single) As Single Dim S As Single If x1 = x2 Then S = 0: GoTo Finish
Dim N As Integer, i As Integer, j As Integer, k As Integer, R As Single, T As Single Dim dx As Single, dx2 As Single, dx3 As Single, dx4 As Single, Z
N = 0 For Each Z In Arg: N = N + 1: Next ReDim X(N) As Single, Y(N) As Single, b(N) As Double, c(N) As Double, d(N) As Double i = 0 For Each Z In Arg: i = i + 1: X(i) = Z: Next i = 0 For Each Z In Fn: i = i + 1: Y(i) = Z: Next '========================= S p l i n e ======================== d(1) = X(2) - X(1): c(2) = (Y(2) - Y(1)) / d(1) For i = 1 To N - 1 d(i) = X(i + 1) - X(i) b(i) = 2 * (d(i - 1) + d(i)) c(i + 1) = (Y(i + 1) - Y(i)) / d(i) c(i) = c(i + 1) - c(i) Next i b(1) = -d(1): b(N) = -d(N - 1): c(1) = 0 c(1) = c(3) / (X(4) - X(2)) - c(2) / (X(3) - X(1)) c(N) = c(N - 1) / (X(N) - X(N - 2)) - c(N - 2) / (X(N - 1) - X(N - 3)) c(1) = c(1) * d(1) ^ 2 / (X(4) - X(1)) c(N) = -c(N) * d(N - 1) ^ 2 / (X(N) - X(N - 3)) For i = 2 To N T = d(i - 1) / b(i - 1) b(i) = b(i) - T * d(i - 1) c(i) = c(i) - T * c(i - 1) Next i c(N) = c(N) / b(N) For j = 1 To N - 1 i = N - j c(i) = (c(i) - d(i) * c(i + 1)) / b(i) Next j j = N - 1 b(N) = (Y(N) - Y(i)) / d(j) + d(j) * (c(j) + 2 * c(N)) For i = 1 To j b(i) = (Y(i + 1) - Y(i)) / d(i) - d(i) * (c(i + 1) + 2 * c(i)) d(i) = (c(i + 1) - c(i)) / d(i) c(i) = 3 * c(i) Next i c(N) = 3 * c(N): d(N) = d(N - 1) '====================== Вычисление интегралов ===================== For i = 1 To N - 1 If X(i) > x1 Then Exit For Next i i = i - 1 ' Нахождение левой границы узлового интервала, в котором лежит Х1 ' - - - - - - - - - - - - - - - - - - - - - For j = i To N - 1 If X(j) > x2 Then Exit For Next j j = j - 1 ' Нахождение левой границы узлового интервала, в котором лежит Х2 ' - - - - - - - - - - - - - - - - - - - - - If i = j Then ' Если Х1 и Х2 лежат внутри одного и того же интертвала dx = x2 - x1 dx2 = ((x2 - X(i)) ^ 2 - (x1 - X(i)) ^ 2) / 2 dx3 = ((x2 - X(i)) ^ 3 - (x1 - X(i)) ^ 3) / 3 dx4 = ((x2 - X(i)) ^ 4 - (x1 - X(i)) ^ 4) / 4 S = Y(i) * dx + b(i) * dx2 + c(i) * dx3 + d(i) * dx4 GoTo Finish End If ' - - - - - - - - - - - - - - - - - - - - - dx = X(i + 1) - x1 dx2 = ((X(i + 1) - X(i)) ^ 2 - (x1 - X(i)) ^ 2) / 2 dx3 = ((X(i + 1) - X(i)) ^ 3 - (x1 - X(i)) ^ 3) / 3 dx4 = ((X(i + 1) - X(i)) ^ 4 - (x1 - X(i)) ^ 4) / 4 S = Y(i) * dx + b(i) * dx2 + c(i) * dx3 + d(i) * dx4 ' Интеграл от Х1 до правой границы интервала ' - - - - - - - - - - - - - - - - - - - - - dx = x2 - X(j) dx2 = dx ^ 2 / 2 dx3 = dx ^ 3 / 3 dx4 = dx ^ 4 / 4 T = Y(j) * dx + b(j) * dx2 + c(j) * dx3 + d(j) * dx4 ' Интеграл от левой границы интервала до Х2 ' - - - - - - - - - - - - - - - - - - - - - S = S + T ' Интеграл по обоим дробным интервалам ' - - - - - - - - - - - - - - - - - - - - - For k = i + 1 To j - 1 ' Интеграл по целым интервалам между Х1 и Х2 dx = X(k + 1) - X(k) dx2 = dx ^ 2 / 2 dx3 = dx2 * dx dx4 = dx3 * dx T = Y(k) * dx + b(k) * dx2 + c(k) * dx3 + d(k) * dx4 S = S + T Next k ' - - - - - - - - - - - - - - - - - - - - - Finish: INTEGRAL = S End Function
_________________ Мудрость - это понимание своего бессилия перед глупостью. Во имя овса и сена, и свиного уха
|