неділю, 9 вересня 2007 р.

Ruby у математиці - частина перша (обчислення подвійного інтегралу)

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

У якості мови програмування я обрав Ruby. Ця мова хоч і досить молода проте стрімко набирає популярності. Я не буду роз'яснювати як встановити інтерпретатор Ruby (в Ubuntu цн робиться через менеджер пакетів як і для будь-якої іншої програми), а також не буду проводити курс навчання основним конструкціям мови, все буде пояснюватися на конкретних прикладах.

Обчислення подвійного інтегралу

Почнемо з чисельного визначення значення подвійного інтегралу. З курсу математики відомо, що якщо є область S для якої справедливо:

де y1, y2 - неперервні функції на [a;b], то


тобто подвійний інтеграл може бути вируховано в результаті двох послідовно проведених інтегрувань.

Алгоритм обчислення подвійного інтегралу не складний. Якщо ми візьмемо область обмежену прямими x=a та x=b, і кривими y=y1(x) та y=y2(x), то розіб'ємо її на досить друбні квадрати по горизонталі та вертикалі, ми можемо вирахувати значення інтегралу. Для цього потрібно знайти значення функції y=f(x,y) у центральній точці кожного з цих квадратів помножене на площу квадрата і просумувати їх разом. На Ruby така програма матиме такий вигляд:

# Обчислення подвійного інтегралу
include Math

puts "Обчислення подвійного інтегралу"
print "Введіть a="; a = gets.to_f
print "Введіть b="; b = gets.to_f
print "Введіть функцію y1(x): y="; y1 = gets.to_s
print "Введіть функцію y2(x): y="; y2 = gets.to_s
print "Введіть інтегральну функцію f="; f = gets.to_s
print "Задайте крок step="; step = gets.to_f

i=a
sum,ty1,ty2,j,x,y=0

while i<=b do
x=i
ty1=eval(y1) ; ty2=eval(y2)
j=ty1
while j<=ty2 do
x=(i+i+step)/2
y=(j+j+step)/2
sum+=eval(f)*step*step
j+=step
end
i+=step
end

puts "==========================================="
puts "Значення інтегралу: #{sum}"


Якщо тепер запустити дану програму на виконання, то результат буде наступним (я тут придумав простий контрольний приклад):

bum@impress:~/Sources/Ruby/dint$ ruby dint.rb
Обчислення подвійного інтегралу
Введіть a=0
Введіть b=1
Введіть функцію y1(x): y=x*x
Введіть функцію y2(x): y=sqrt(x)
Введіть інтегральну функцію f=x*y
Задайте крок step=0.001
===========================================
Значення інтегралу: 0.0836083670627215


Що ж, для перевірки правильності роботи програми знайдемо значення інтегралу аналітично:


Як бачимо обчислене наближене значення є досить близьким до аналітичного, відносна похибка становить 0,3%, що цілком нормально.

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

Сам код який відповідає за підрахунок значення інтегралу є дуже простим:

while i<=b do
x=i
ty1=eval(y1) ; ty2=eval(y2) # обчислюємо значення функції y1 та y2 при x=i
j=ty1
while j<=ty2 do
x=(i+i+step)/2 # обчислюємо координати центра квадрата
y=(j+j+step)/2
sum+=eval(f)*step*step # плюсуємо значення функції f(x,y) помножене на площу квадрата
j+=step
end
i+=step
end


Наскільки точним буде наближене значення у порівнянні з аналітичним задається кроком інтегрування, у даному випадку значенням змінної step. Чим дане число менше тим точніший буде результат, але тим більше часу комп'ютер буде витрачати на його знаходження. Усі інші конструкції я думаю повинно бути зрозуміло і без пояснень.

Немає коментарів:

Дописати коментар